<p>Harald Welte has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/14109">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">cbch: Support Extended CBCH<br><br>The logic for Extended CBCH are the same as for the Basic CBCH, we just<br>need to<br>* duplicate our related state<br>* parse the optional RSL_IE_SMSCB_CHAN_INDICATOR IE<br>* start to send data on the Extended CBCH (TB=4..7)<br><br>Change-Id: If2c6dc7da1e2185ab75fc957f8d305ad8db22429<br>Closes: OS#3535<br>---<br>M include/osmo-bts/cbch.h<br>M include/osmo-bts/gsm_data_shared.h<br>M src/common/bts.c<br>M src/common/cbch.c<br>M src/common/rsl.c<br>M src/common/vty.c<br>6 files changed, 69 insertions(+), 37 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/09/14109/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmo-bts/cbch.h b/include/osmo-bts/cbch.h</span><br><span>index b4ac409..af5fd9a 100644</span><br><span>--- a/include/osmo-bts/cbch.h</span><br><span>+++ b/include/osmo-bts/cbch.h</span><br><span>@@ -7,9 +7,8 @@</span><br><span> #include <osmo-bts/bts.h></span><br><span> </span><br><span> /* incoming SMS broadcast command from RSL */</span><br><span style="color: hsl(0, 100%, 40%);">-int bts_process_smscb_cmd(struct gsm_bts *bts,</span><br><span style="color: hsl(0, 100%, 40%);">-                          struct rsl_ie_cb_cmd_type cmd_type,</span><br><span style="color: hsl(0, 100%, 40%);">-                     uint8_t msg_len, const uint8_t *msg);</span><br><span style="color: hsl(120, 100%, 40%);">+int bts_process_smscb_cmd(struct gsm_bts *bts, struct rsl_ie_cb_cmd_type cmd_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                     bool extended_cbch, uint8_t msg_len, const uint8_t *msg);</span><br><span> </span><br><span> /* call-back from bts model specific code when it wants to obtain a CBCH</span><br><span>  * block for a given gsm_time.  outbuf must have 23 bytes of space. */</span><br><span>diff --git a/include/osmo-bts/gsm_data_shared.h b/include/osmo-bts/gsm_data_shared.h</span><br><span>index 6974e62..9378730 100644</span><br><span>--- a/include/osmo-bts/gsm_data_shared.h</span><br><span>+++ b/include/osmo-bts/gsm_data_shared.h</span><br><span>@@ -539,6 +539,12 @@</span><br><span>    uint8_t initial_mcs;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct bts_smscb_state {</span><br><span style="color: hsl(120, 100%, 40%);">+      struct llist_head queue; /* list of struct smscb_msg */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct smscb_msg *cur_msg; /* current SMS-CB */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct smscb_msg *default_msg; /* default broadcast message; NULL if none */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* The amount of time within which a sudden disconnect of a newly established</span><br><span>  * OML connection will cause a special warning to be logged. */</span><br><span> #define OSMO_BTS_OML_CONN_EARLY_DISCONNECT 10  /* in seconds */</span><br><span>@@ -734,11 +740,9 @@</span><br><span>     /* used by the sysmoBTS to adjust band */</span><br><span>    uint8_t auto_band;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                struct llist_head queue;        /* list of struct smscb_msg */</span><br><span style="color: hsl(0, 100%, 40%);">-          struct smscb_msg *cur_msg;      /* current SMS-CB */</span><br><span style="color: hsl(0, 100%, 40%);">-            struct smscb_msg *default_msg;  /* default broadcast message; NULL if none */</span><br><span style="color: hsl(0, 100%, 40%);">-   } smscb_state;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* State for SMSCB (Cell Broadcast) for BASIC and EXTENDED channel */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bts_smscb_state smscb_basic;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct bts_smscb_state smscb_extended;</span><br><span> </span><br><span>   float min_qual_rach;    /* minimum quality for RACH bursts */</span><br><span>        float min_qual_norm;    /* minimum quality for normal daata */</span><br><span>diff --git a/src/common/bts.c b/src/common/bts.c</span><br><span>index 5851e9b..4af219b 100644</span><br><span>--- a/src/common/bts.c</span><br><span>+++ b/src/common/bts.c</span><br><span>@@ -190,7 +190,8 @@</span><br><span>            initialized = 1;</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   INIT_LLIST_HEAD(&bts->smscb_state.queue);</span><br><span style="color: hsl(120, 100%, 40%);">+      INIT_LLIST_HEAD(&bts->smscb_basic.queue);</span><br><span style="color: hsl(120, 100%, 40%);">+      INIT_LLIST_HEAD(&bts->smscb_extended.queue);</span><br><span>  INIT_LLIST_HEAD(&bts->oml_queue);</span><br><span> </span><br><span>         /* register DTX DL FSM */</span><br><span>diff --git a/src/common/cbch.c b/src/common/cbch.c</span><br><span>index c75b510..6092e46 100644</span><br><span>--- a/src/common/cbch.c</span><br><span>+++ b/src/common/cbch.c</span><br><span>@@ -37,6 +37,17 @@</span><br><span>      uint8_t num_segs;               /* total number of segments */</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* determine SMSCB state by tb number */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct bts_smscb_state *bts_smscb_state(struct gsm_bts *bts, uint8_t tb)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        if (tb < 4)</span><br><span style="color: hsl(120, 100%, 40%);">+                return &bts->smscb_basic;</span><br><span style="color: hsl(120, 100%, 40%);">+      else if (tb < 8)</span><br><span style="color: hsl(120, 100%, 40%);">+           return &bts->smscb_extended;</span><br><span style="color: hsl(120, 100%, 40%);">+   else</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> /* construct a SMSCB NULL block in the user-provided output buffer at 'out' */</span><br><span> static int get_smscb_null_block(uint8_t *out)</span><br><span> {</span><br><span>@@ -52,12 +63,12 @@</span><br><span> }</span><br><span> </span><br><span> /* get the next block of the current CB message */</span><br><span style="color: hsl(0, 100%, 40%);">-static int get_smscb_block(struct gsm_bts *bts, uint8_t *out, uint8_t block_nr,</span><br><span style="color: hsl(120, 100%, 40%);">+static int get_smscb_block(struct bts_smscb_state *bts_ss, uint8_t *out, uint8_t block_nr,</span><br><span>                            const struct gsm_time *g_time)</span><br><span> {</span><br><span>       int to_copy;</span><br><span>         struct gsm412_block_type *block_type;</span><br><span style="color: hsl(0, 100%, 40%);">-   struct smscb_msg *msg = bts->smscb_state.cur_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct smscb_msg *msg = bts_ss->cur_msg;</span><br><span> </span><br><span>      if (!msg) {</span><br><span>          /* No message: Send NULL block */</span><br><span>@@ -101,11 +112,11 @@</span><br><span>            block_type->lb = 0;</span><br><span> </span><br><span>   if (block_nr == 4) {</span><br><span style="color: hsl(0, 100%, 40%);">-            if (msg != bts->smscb_state.default_msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (msg != bts_ss->default_msg) {</span><br><span>                         DEBUGPGT(DLSMS, g_time, "deleting fully-transmitted message %p\n", msg);</span><br><span>                   /* delete any fully-transmitted normal message (or superseded default) */</span><br><span style="color: hsl(0, 100%, 40%);">-                       talloc_free(bts->smscb_state.cur_msg);</span><br><span style="color: hsl(0, 100%, 40%);">-                       bts->smscb_state.cur_msg = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                   talloc_free(bts_ss->cur_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                      bts_ss->cur_msg = NULL;</span><br><span>           } else {</span><br><span>                     DEBUGPGT(DLSMS, g_time, "keeping fully-transmitted default message %p\n", msg);</span><br><span>            }</span><br><span>@@ -131,11 +142,16 @@</span><br><span> </span><br><span> </span><br><span> /* incoming SMS broadcast command from RSL */</span><br><span style="color: hsl(0, 100%, 40%);">-int bts_process_smscb_cmd(struct gsm_bts *bts,</span><br><span style="color: hsl(0, 100%, 40%);">-                          struct rsl_ie_cb_cmd_type cmd_type,</span><br><span style="color: hsl(0, 100%, 40%);">-                     uint8_t msg_len, const uint8_t *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+int bts_process_smscb_cmd(struct gsm_bts *bts, struct rsl_ie_cb_cmd_type cmd_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                      bool extended_cbch, uint8_t msg_len, const uint8_t *msg)</span><br><span> {</span><br><span>      struct smscb_msg *scm;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct bts_smscb_state *bts_ss;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (extended_cbch)</span><br><span style="color: hsl(120, 100%, 40%);">+            bts_ss = &bts->smscb_extended;</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+          bts_ss = &bts->smscb_basic;</span><br><span> </span><br><span>       if (msg_len > sizeof(scm->msg)) {</span><br><span>              LOGP(DLSMS, LOGL_ERROR,</span><br><span>@@ -157,7 +173,8 @@</span><br><span>        scm->num_segs = last_block_rsl2um[cmd_type.last_block&3];</span><br><span>     memcpy(scm->msg, msg, msg_len);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  LOGP(DLSMS, LOGL_INFO, "RSL SMSCB COMMAND (type=%s, num_blocks=%u)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+      LOGP(DLSMS, LOGL_INFO, "RSL SMSCB COMMAND (chan=%s, type=%s, num_blocks=%u)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+             extended_cbch ? "EXTENDED" : "BASIC",</span><br><span>            get_value_string(rsl_cb_cmd_names, cmd_type.command), scm->num_segs);</span><br><span> </span><br><span>         switch (cmd_type.command) {</span><br><span>@@ -165,20 +182,20 @@</span><br><span>  case RSL_CB_CMD_TYPE_SCHEDULE:</span><br><span>       case RSL_CB_CMD_TYPE_NULL:</span><br><span>           /* def_bcast is ignored as per Section 9.3.41 of 3GPP TS 48.058 */</span><br><span style="color: hsl(0, 100%, 40%);">-              llist_add_tail(&scm->list, &bts->smscb_state.queue);</span><br><span style="color: hsl(120, 100%, 40%);">+            llist_add_tail(&scm->list, &bts_ss->queue);</span><br><span>            /* FIXME: limit queue size and optionally send CBCH LOAD Information (overflow) via RSL */</span><br><span>           break;</span><br><span>       case RSL_CB_CMD_TYPE_DEFAULT:</span><br><span>                /* old default msg will be free'd in get_smscb_block() if it is currently in transit</span><br><span>              * and we set a new default_msg here */</span><br><span style="color: hsl(0, 100%, 40%);">-         if (bts->smscb_state.cur_msg && bts->smscb_state.cur_msg == bts->smscb_state.default_msg)</span><br><span style="color: hsl(0, 100%, 40%);">-                      talloc_free(bts->smscb_state.cur_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+             if (bts_ss->cur_msg && bts_ss->cur_msg == bts_ss->default_msg)</span><br><span style="color: hsl(120, 100%, 40%);">+                       talloc_free(bts_ss->cur_msg);</span><br><span>             if (cmd_type.def_bcast == RSL_CB_CMD_DEFBCAST_NORMAL)</span><br><span>                        /* def_bcast == 0: normal message */</span><br><span style="color: hsl(0, 100%, 40%);">-                    bts->smscb_state.default_msg = scm;</span><br><span style="color: hsl(120, 100%, 40%);">+                        bts_ss->default_msg = scm;</span><br><span>                else {</span><br><span>                       /* def_bcast == 1: NULL message */</span><br><span style="color: hsl(0, 100%, 40%);">-                      bts->smscb_state.default_msg = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                       bts_ss->default_msg = NULL;</span><br><span>                       talloc_free(scm);</span><br><span>            }</span><br><span>            break;</span><br><span>@@ -190,11 +207,12 @@</span><br><span>       return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static struct smscb_msg *select_next_smscb(struct gsm_bts *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct smscb_msg *select_next_smscb(struct gsm_bts *bts, uint8_t tb)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+   struct bts_smscb_state *bts_ss = bts_smscb_state(bts, tb);</span><br><span>   struct smscb_msg *msg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      msg = llist_first_entry_or_null(&bts->smscb_state.queue, struct smscb_msg, list);</span><br><span style="color: hsl(120, 100%, 40%);">+      msg = llist_first_entry_or_null(&bts_ss->queue, struct smscb_msg, list);</span><br><span>      if (msg) {</span><br><span>           llist_del(&msg->list);</span><br><span>                DEBUGP(DLSMS, "%s: Dequeued msg\n", __func__);</span><br><span>@@ -204,7 +222,7 @@</span><br><span>       /* FIXME: send CBCH LOAD Information (underflow) via RSL */</span><br><span> </span><br><span>      /* choose the default message, if any */</span><br><span style="color: hsl(0, 100%, 40%);">-        msg = bts->smscb_state.default_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+        msg = bts_ss->default_msg;</span><br><span>        if (msg) {</span><br><span>           DEBUGP(DLSMS, "%s: Using default msg\n", __func__);</span><br><span>                return msg;</span><br><span>@@ -219,10 +237,14 @@</span><br><span> int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time)</span><br><span> {</span><br><span>  uint32_t fn = gsm_gsmtime2fn(g_time);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bts_smscb_state *bts_ss;</span><br><span>      /* According to 05.02 Section 6.5.4 */</span><br><span>       uint32_t tb = (fn / 51) % 8;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t block_nr = tb % 4;</span><br><span>   int rc = 0;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       bts_ss = bts_smscb_state(bts, tb);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         /* The multiframes used for the basic cell broadcast channel</span><br><span>          * shall be those in * which TB = 0,1,2 and 3. The multiframes</span><br><span>        * used for the extended cell broadcast channel shall be those</span><br><span>@@ -234,16 +256,14 @@</span><br><span> </span><br><span>   switch (tb) {</span><br><span>        case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+       case 4:</span><br><span>              /* select a new SMSCB message */</span><br><span style="color: hsl(0, 100%, 40%);">-                bts->smscb_state.cur_msg = select_next_smscb(bts);</span><br><span style="color: hsl(0, 100%, 40%);">-           rc = get_smscb_block(bts, outbuf, tb, g_time);</span><br><span style="color: hsl(120, 100%, 40%);">+                bts_ss->cur_msg = select_next_smscb(bts, tb);</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = get_smscb_block(bts_ss, outbuf, block_nr, g_time);</span><br><span>              break;</span><br><span>       case 1: case 2: case 3:</span><br><span style="color: hsl(0, 100%, 40%);">-         rc = get_smscb_block(bts, outbuf, tb, g_time);</span><br><span style="color: hsl(0, 100%, 40%);">-          break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case 4: case 5: case 6: case 7:</span><br><span style="color: hsl(0, 100%, 40%);">-         /* always send NULL frame in extended CBCH for now */</span><br><span style="color: hsl(0, 100%, 40%);">-           rc = get_smscb_null_block(outbuf);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 5: case 6: case 7:</span><br><span style="color: hsl(120, 100%, 40%);">+               rc = get_smscb_block(bts_ss, outbuf, block_nr, g_time);</span><br><span>              break;</span><br><span>       }</span><br><span> </span><br><span>diff --git a/src/common/rsl.c b/src/common/rsl.c</span><br><span>index 9284e6f..fda1c32 100644</span><br><span>--- a/src/common/rsl.c</span><br><span>+++ b/src/common/rsl.c</span><br><span>@@ -487,6 +487,7 @@</span><br><span>     struct abis_rsl_cchan_hdr *cch = msgb_l2(msg);</span><br><span>       struct tlv_parsed tp;</span><br><span>        struct rsl_ie_cb_cmd_type *cb_cmd_type;</span><br><span style="color: hsl(120, 100%, 40%);">+       bool extended_cbch = false;</span><br><span>  int rc;</span><br><span> </span><br><span>  rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));</span><br><span>@@ -495,11 +496,16 @@</span><br><span>           !TLVP_PRESENT(&tp, RSL_IE_SMSCB_MSG))</span><br><span>                return rsl_tx_error_report(trx, RSL_ERR_MAND_IE_ERROR, &cch->chan_nr, NULL, msg);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  if (TLVP_PRESENT(&tp, RSL_IE_SMSCB_CHAN_INDICATOR)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if ((*TLVP_VAL(&tp, RSL_IE_SMSCB_CHAN_INDICATOR) & 0x0f) == 0x01)</span><br><span style="color: hsl(120, 100%, 40%);">+                     extended_cbch = true;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  cb_cmd_type = (struct rsl_ie_cb_cmd_type *)</span><br><span>                                  TLVP_VAL(&tp, RSL_IE_CB_CMD_TYPE);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      rc = bts_process_smscb_cmd(trx->bts, *cb_cmd_type, TLVP_LEN(&tp, RSL_IE_SMSCB_MSG),</span><br><span style="color: hsl(0, 100%, 40%);">-                                 TLVP_VAL(&tp, RSL_IE_SMSCB_MSG));</span><br><span style="color: hsl(120, 100%, 40%);">+      rc = bts_process_smscb_cmd(trx->bts, *cb_cmd_type, extended_cbch,</span><br><span style="color: hsl(120, 100%, 40%);">+                             TLVP_LEN(&tp, RSL_IE_SMSCB_MSG), TLVP_VAL(&tp, RSL_IE_SMSCB_MSG));</span><br><span>        if (rc < 0)</span><br><span>               return rsl_tx_error_report(trx, RSL_ERR_IE_CONTENT, &cch->chan_nr, NULL, msg);</span><br><span> </span><br><span>diff --git a/src/common/vty.c b/src/common/vty.c</span><br><span>index 9e900b2..53a8674 100644</span><br><span>--- a/src/common/vty.c</span><br><span>+++ b/src/common/vty.c</span><br><span>@@ -865,8 +865,10 @@</span><br><span>                bts->agch_queue.rejected_msgs, bts->agch_queue.agch_msgs,</span><br><span>              bts->agch_queue.pch_msgs,</span><br><span>                 VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">-   vty_out(vty, "  CBCH backlog queue length: %u%s",</span><br><span style="color: hsl(0, 100%, 40%);">-             llist_length(&bts->smscb_state.queue), VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+   vty_out(vty, "  CBCH backlog queue length (BASIC): %u%s",</span><br><span style="color: hsl(120, 100%, 40%);">+           llist_length(&bts->smscb_basic.queue), VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+   vty_out(vty, "  CBCH backlog queue length (EXTENDED): %u%s",</span><br><span style="color: hsl(120, 100%, 40%);">+                llist_length(&bts->smscb_extended.queue), VTY_NEWLINE);</span><br><span>       vty_out(vty, "  Paging: queue length %d, buffer space %d%s",</span><br><span>               paging_queue_length(bts->paging_state), paging_buffer_space(bts->paging_state),</span><br><span>                VTY_NEWLINE);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/14109">change 14109</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/14109"/><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-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: If2c6dc7da1e2185ab75fc957f8d305ad8db22429 </div>
<div style="display:none"> Gerrit-Change-Number: 14109 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Harald Welte <laforge@gnumonks.org> </div>