<p>Neels Hofmeyr has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/9489">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">doc: charts: illustrate new plan for ts and lchans<br><br>Add lchan and timeslot FSM charts to illustrate planning of how osmo-bsc should<br>handle lchan assignment and release.<br><br>Modify assignment, handover, lchan-release charts according to the new plan.<br><br>Change-Id: I18d60de5ee932c962aad0a532965a55d570bb936<br>---<br>M doc/Makefile.am<br>M doc/assignment.msc<br>A doc/handover-inter-bsc-mo.msc<br>A doc/handover-inter-bsc-mt.msc<br>M doc/handover.msc<br>A doc/lchan-fsm.dot<br>M doc/lchan-release.msc<br>A doc/lchan.msc<br>M doc/ms-channel-request.msc<br>A doc/timeslot-fsm.dot<br>A doc/timeslot.msc<br>A doc/ts-and-lchan-fsm-lifecycle.msc<br>12 files changed, 1,098 insertions(+), 466 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/89/9489/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/Makefile.am b/doc/Makefile.am</span><br><span>index 5fe5674..ca0470d 100644</span><br><span>--- a/doc/Makefile.am</span><br><span>+++ b/doc/Makefile.am</span><br><span>@@ -7,11 +7,24 @@</span><br><span>       $(builddir)/assignment.png \</span><br><span>         $(builddir)/lchan-release.png \</span><br><span>      $(builddir)/ms-channel-request.png \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(builddir)/timeslot.png \</span><br><span style="color: hsl(120, 100%, 40%);">+    $(builddir)/lchan.png \</span><br><span style="color: hsl(120, 100%, 40%);">+       $(builddir)/ts-and-lchan-fsm-lifecycle.png \</span><br><span style="color: hsl(120, 100%, 40%);">+  $(builddir)/handover-inter-bsc-mo.png \</span><br><span style="color: hsl(120, 100%, 40%);">+       $(builddir)/handover-inter-bsc-mt.png \</span><br><span style="color: hsl(120, 100%, 40%);">+       $(NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dot: \</span><br><span style="color: hsl(120, 100%, 40%);">+     $(builddir)/timeslot-fsm.png \</span><br><span style="color: hsl(120, 100%, 40%);">+        $(builddir)/lchan-fsm.png \</span><br><span>  $(NULL)</span><br><span> </span><br><span> $(builddir)/%.png: $(srcdir)/%.msc</span><br><span>    mscgen -T png -o $@ $<</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+$(builddir)/%.png: $(srcdir)/%.dot</span><br><span style="color: hsl(120, 100%, 40%);">+     dot -Tpng $< > $@</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> .PHONY: poll</span><br><span> poll:</span><br><span style="color: hsl(0, 100%, 40%);">-      while true; do $(MAKE) msc; sleep 1; done</span><br><span style="color: hsl(120, 100%, 40%);">+     while true; do $(MAKE) msc dot; sleep 1; done</span><br><span>diff --git a/doc/assignment.msc b/doc/assignment.msc</span><br><span>index d470d01..9f10ea1 100644</span><br><span>--- a/doc/assignment.msc</span><br><span>+++ b/doc/assignment.msc</span><br><span>@@ -1,190 +1,126 @@</span><br><span> msc {</span><br><span>    hscale=3;</span><br><span style="color: hsl(0, 100%, 40%);">-       ms [label="MS"], bts [label="BTS"], bsc[label="BSC"], bsc_gscon[label="BSC conn FSM"], bsc_mgcp[label="BSC mgcp FSM"], mgw[label="MGW"], msc_[label="MSC"];</span><br><span style="color: hsl(120, 100%, 40%);">+     ms [label="MS/BTS"], bsc_lchan[label="BSC lchan FSM"],</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon[label="BSC conn FSM"], bsc_mgcp[label="BSC mgcp FSM"], mgw_msc[label="MGW/MSC"];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    ms note msc_ [label="lchan allocation sequence for BSSMAP Assignment Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+     ms note mgw_msc [label="lchan allocation sequence for BSSMAP Assignment Request"];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        bsc <= msc_ [label="BSSMAP Assignment Request"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="bssmap_handle_assignm_req()"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc -> bsc_gscon [label="GSCON_EV_A_ASSIGNMENT_CMD"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon <= mgw_msc [label="BSSMAP Assignment Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_ASSIGNMENT_\nWAIT_LCHAN"];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    --- [label="is the chan_mode a speech mode?"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan <- bsc_gscon [label="lchan_select_by_chan_mode(chan_mode)"];</span><br><span style="color: hsl(120, 100%, 40%);">+   |||;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="IF returned lchan is NULL"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</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%);">+  bsc_gscon box bsc_gscon [label="store lchan pointer in conn->lchan_for_assignment"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan <- bsc_gscon [label="lchan_activate(FOR_ASSIGNMENT)"];</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%);">+  --- [label="on lchan FSM error or timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon box bsc_gscon [label="'forget' all about conn->lchan_for_assignment"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="END: 'on error'"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  ...;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        bsc_gscon abox bsc_gscon [label="ST_WAIT_CRCX_BTS (MGCP_MGW_TIMEOUT = 4s)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="IF lchan FSM decides that it is an lchan for speech"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan -> bsc_gscon [label="GSCON_EV_ENSURE_MGW_ENDPOINT"];</span><br><span style="color: hsl(120, 100%, 40%);">+   --- [label="IF there is an MGW endpoint for the BTS already (conn->user_plane.fi_bts)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="ELSE: no MGW endpoint for the BTS side yet"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon abox bsc_gscon [label="ST_ASSIGNMENT_\nWAIT_CRCX_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon box bsc_gscon [label="assignment_created_mgw_endpoint = true"];</span><br><span>  bsc_gscon -> bsc_mgcp [label="mgcp_conn_create()"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc_mgcp => mgw [label="CRCX (for BTS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc_mgcp abox bsc_mgcp [label="ST_CRCX (MGCP_MGW_TIMEOUT = 4s)"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc_gscon note bsc_mgcp [label="two timeouts running in parallel"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc_gscon note bsc_mgcp [label="note: #define MGCP_MGW_TIMEOUT exists twice,</span><br><span style="color: hsl(0, 100%, 40%);">-                                      once in libosmo-mgcp-client,</span><br><span style="color: hsl(0, 100%, 40%);">-                                    once in bsc_subscr_conn_fsm.c"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc_mgcp -> bsc_gscon [label="mgcp_conn_create() exits"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc_gscon -> bsc [label="bssmap_handle_assignm_req() exits"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_mgcp abox bsc_mgcp [label="ST_CRCX_RESP (MGCP_MGW_TIMEOUT = 4s)"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_mgcp => mgw_msc [label="CRCX (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon note bsc_mgcp [label="conn FSM relies on mgcp FSM timeout"];</span><br><span>     ...;</span><br><span>         --- [label="On Timeout"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc_gscon note bsc_gscon [label="The conn FSM likely timeouts first"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc_gscon => msc_ [label="BSSMAP Assignment Failure"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_mgcp note bsc_mgcp [label="The MGCP FSM will timeout right after that, and terminate itself,</span><br><span style="color: hsl(0, 100%, 40%);">-                                 emitting the parent_term event set upon mgcp_conn_create():"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_mgcp note bsc_mgcp [label="On timeouit, the MGCP FSM will terminate, emitting the parent_term</span><br><span style="color: hsl(120, 100%, 40%);">+                event set upon mgcp_conn_create():"];</span><br><span>   bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS"];</span><br><span>  bsc_gscon note bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS is handled by the conn FSM allstate</span><br><span style="color: hsl(0, 100%, 40%);">-                                 handler. It sets conn->user_plane.fi_bts = NULL. There is code</span><br><span style="color: hsl(0, 100%, 40%);">-                                       that would emit a BSSMAP Assignment Failure, but not in</span><br><span style="color: hsl(0, 100%, 40%);">-                                 ST_ACTIVE"];</span><br><span style="color: hsl(0, 100%, 40%);">-       --- [label="end: 'On Timeout'"];</span><br><span style="color: hsl(120, 100%, 40%);">+            handler. It sets conn->user_plane.fi_bts = NULL."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan note bsc_gscon [label="conn FSM timeout handler exits and relies on the lchan FSM</span><br><span style="color: hsl(120, 100%, 40%);">+              signalling error, which should actually happen immediately:"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon <- bsc_lchan [label="GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon box bsc_gscon [label="'forget' all about conn->lchan_for_assignment"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="END: 'On Timeout'"];</span><br><span>   ...;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        bsc_mgcp <= mgw [label="CRCX OK (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_mgcp <= mgw_msc [label="CRCX OK (for BTS)"];</span><br><span>        bsc_mgcp box bsc_mgcp [label="libosmo-mgcp-client fsm_crcx_resp_cb()"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_mgcp abox bsc_mgcp [label="ST_READY"];</span><br><span>         bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_CRCX_RESP_BTS"];</span><br><span style="color: hsl(0, 100%, 40%);">-        --- [label="end: 'is the chan_mode a speech mode?'"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_gscon note bsc_gscon [label="for mode=sign, we're still handling GSCON_EV_A_ASSIGNMENT_CMD;</span><br><span style="color: hsl(0, 100%, 40%);">-                                         for speech mode, we're handling GSCON_EV_MGW_CRCX_RESP_BTS"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc <- bsc_gscon [label="gsm0808_assign_req()"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="lchan_alloc(): pick available lchan"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="rsl_chan_activate_lchan()"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      --- [label="is the chosen lchan on dynamic timeslot that is currently used as PDCH?"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bts <= bsc [label="i) RSL RF Chan Release of PDCH (Osmocom dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bts <= bsc [label="OR ii) RSL PDCH Deact (ip.access dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc -> bsc_gscon [label="gsm0808_assign_req() returns early"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc_gscon abox bsc_gscon [label="ST_WAIT_ASS_COMPL (GSM0808_T10_VALUE=6s)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_ASSIGNMENT_\nWAIT_LCHAN"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="END: lchan FSM decides that it is an lchan for speech"];</span><br><span>       ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-          label="Osmocom style dyn TS use lchan->act_timer to watch over RF Chan Release, but there</span><br><span style="color: hsl(0, 100%, 40%);">-               seems to be no timer watching over PDCH Deact!"];</span><br><span>       ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="i) RSL RF Chan Release ACK (Osmocom dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bts => bsc [label="OR ii) RSL PDCH Deact ACK (ip.access dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="rsl_chan_activate_lchan() re-invoked"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="lchan->state = LCHAN_S_ACT_REQ"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bts <= bsc [label="RSL Chan Activ"];</span><br><span style="color: hsl(0, 100%, 40%);">-       --- [label="else (no dyn TS switchover)"];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="lchan->state = LCHAN_S_ACT_REQ"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bts <= bsc [label="RSL Chan Activ"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc -> bsc_gscon [label="gsm0808_assign_req() returns"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc_gscon abox bsc_gscon [label="ST_WAIT_ASS_COMPL (GSM0808_T10_VALUE=6s)"];</span><br><span style="color: hsl(0, 100%, 40%);">-  ---;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon abox bsc_gscon [label="ST_ASSIGNMENT_\nWAIT_COMPLETE\nT10, 6s"];</span><br><span style="color: hsl(120, 100%, 40%);">+  ms <= bsc_gscon [label="RR Assignment"];</span><br><span>        ...;</span><br><span>         --- [label="On Timeout"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc_gscon => msc_ [label="BSSMAP Assignment Failure"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon -> bsc_lchan [label="LCHAN_EV_LCHAN_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon box bsc_gscon [label="'forget' all about conn->lchan_for_assignment"];</span><br><span style="color: hsl(120, 100%, 40%);">+ --- [label="IF assignment_created_mgw_endpoint == true"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon note bsc_mgcp [label="If the MGW endpoint didn't exist before the Assignment, release</span><br><span style="color: hsl(120, 100%, 40%);">+              it now. If there was one before this, it is probably still in use by a previous lchan, so</span><br><span style="color: hsl(120, 100%, 40%);">+             keep it in place."];</span><br><span>    bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_gscon note bsc_mgcp [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-       label="The mgcp FSM from CRCX above apparently lacks a cleanup action for this case.</span><br><span style="color: hsl(0, 100%, 40%);">-              It should be cleaned up eventually when the conn is torn down, but we should</span><br><span style="color: hsl(0, 100%, 40%);">-            release RTP endpoints as soon as possible."];</span><br><span style="color: hsl(0, 100%, 40%);">-     --- [label="end: 'On Timeout'"];</span><br><span style="color: hsl(120, 100%, 40%);">+    --- [label="END: 'On Timeout'"];</span><br><span>   ...;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="RSL Chan Activ ACK"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="rsl_rx_chan_act_ack()"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc box bsc [label="Stop lchan->act_timer"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="lchan->state = LCHAN_S_ACTIVE"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc -> bsc [label="S_LCHAN_ACTIVATE_ACK"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="bsc_api.c handle_chan_ack()"];</span><br><span style="color: hsl(0, 100%, 40%);">-    ms <= bsc [label="RR Assignment Command"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    ms note bsc_gscon [label="We rely on the overall conn FSM ST_WAIT_ASS_COMPL timeout."];</span><br><span style="color: hsl(0, 100%, 40%);">-       ...;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    ms => bsc [label="RR Assignment Complete"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="handle_ass_compl()"];</span><br><span style="color: hsl(0, 100%, 40%);">-     --- [label="Release old lchan"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc box bsc [label="_lchan_handle_release(sacch_deact=0)"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="rsl_release_sapis_from(start=1)"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bts <= bsc [label="RSL Release Request (Local End)..."];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts <= bsc [label="...for each SAPI except link_id=0"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="rsl_release_request(link_id=0)"];</span><br><span style="color: hsl(0, 100%, 40%);">- bts <= bsc [label="RSL Release Request (Local End) for link_id=0"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="_lchan_handle_release() returns here, the remaining release is asynchronous;</span><br><span style="color: hsl(0, 100%, 40%);">-                       see `End: 'Release old lchan'` below."];</span><br><span style="color: hsl(0, 100%, 40%);">-       ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-    label="There seems to be no timer watching over RSL Release Request!"];</span><br><span style="color: hsl(0, 100%, 40%);">-     ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="RSL Release Confirm..."];</span><br><span style="color: hsl(0, 100%, 40%);">-       bts => bsc [label="...for each SAPI and link_id=0"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc abox bsc [label="start T3111"];</span><br><span style="color: hsl(0, 100%, 40%);">-   ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="T3111 expires"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc abox bsc [label="Start lchan->act_timer with lchan_deact_tmr_cb"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bts <= bsc [label="RSL RF Channel Release"];</span><br><span style="color: hsl(0, 100%, 40%);">-       ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    --- [label="On timeout"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc box bsc [label="lchan_deact_tmr_cb()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="rsl_lchan_mark_broken(): state=LCHAN_S_BROKEN"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc box bsc [label="lchan_free()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc -> bsc [label="S_LCHAN_UNEXPECTED_RELEASE"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="bsc_api.c handle_release()"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc box bsc [label="bsc->assign_fail()"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc -> bsc_gscon [label="GSCON_EV_RR_ASS_FAIL"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc note bsc_gscon [linecolor="orange",</span><br><span style="color: hsl(0, 100%, 40%);">-         label="The name 'RR_ASS_FAIL' might suggest the event means an actual RR Assignment</span><br><span style="color: hsl(0, 100%, 40%);">-               Failure message being received. Maybe this should be called GSCON_EV_ASSIGNMENT_ERROR."];</span><br><span style="color: hsl(0, 100%, 40%);">- ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="bsc->clear_request()"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="bsc_clear_request encodes a BSSMAP Clear Request message and passes it on</span><br><span style="color: hsl(0, 100%, 40%);">-                          to the conn FSM as data argument via:"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc -> bsc_gscon [label="GSCON_EV_TX_SCCP"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc_gscon => msc_ [label="BSSMAP Clear Request"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-    label="Instead of sending an arbitrary message, the conn FSM should</span><br><span style="color: hsl(0, 100%, 40%);">-               be explicitly instructed to clear the connection, to be able</span><br><span style="color: hsl(0, 100%, 40%);">-            to notice if the MSC failed to respond to the Clear Request.</span><br><span style="color: hsl(0, 100%, 40%);">-            Currently, this relies on the MSC responding with a Clear</span><br><span style="color: hsl(0, 100%, 40%);">-               Command, hopefully, some time later."];</span><br><span style="color: hsl(0, 100%, 40%);">-   --- [label="End: 'On timeout'"];</span><br><span style="color: hsl(0, 100%, 40%);">-      ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="RSL RF Channel Release Ack"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="Stop lchan->act_timer"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="Stop lchan->T3111"];</span><br><span style="color: hsl(0, 100%, 40%);">-   --- [label="End: 'Release old lchan'"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="still in handle_ass_compl()"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc note bsc [label="officially take over new lchan: conn->lchan = conn->secondary_lchan"];</span><br><span style="color: hsl(0, 100%, 40%);">-     --- [label="is BTS using IPA Abis? (osmo-bts, ip.access)"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts <= bsc [label="IPACC CRCX"];</span><br><span style="color: hsl(0, 100%, 40%);">-   ---;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc -> bsc [label="handle_ass_compl() calls bsc_api->assign_compl()"];</span><br><span style="color: hsl(0, 100%, 40%);">-  --- [label="is BTS using IPA Abis? (osmo-bts, ip.access) && conn->user_plane.rtp_ip"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc box bsc [label="bsc_assign_compl()"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc note bsc [label="set ass_compl.valid = true,</span><br><span style="color: hsl(0, 100%, 40%);">-                       postponing GSCON_EV_RR_ASS_COMPL until after the</span><br><span style="color: hsl(0, 100%, 40%);">-                        IPACC MDCX ACK received in osmo_bsc_audio.c"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="exit early: bsc_assign_compl()"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="exit early: handle_ass_compl()"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="osmo_bsc_audio.c"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bts => bsc [label="IPACC CRCX ACK"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bts <= bsc [label="IPACC MDCX"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts => bsc [label="IPACC MDCX ACK"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="handle_abisip_signal()"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc -> bsc_gscon [label="GSCON_EV_RR_ASS_COMPL"];</span><br><span style="color: hsl(0, 100%, 40%);">-  --- [label="else"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="bsc_assign_compl()"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc -> bsc_gscon [label="GSCON_EV_RR_ASS_COMPL"];</span><br><span style="color: hsl(0, 100%, 40%);">-  --- ;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   --- [label="is chan_mode a speech mode?"];</span><br><span style="color: hsl(120, 100%, 40%);">+  ms => bsc_gscon [label="RR Assignment Complete"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon -> bsc_lchan [label="OLD lchan: LCHAN_EV_LCHAN_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon box bsc_gscon [label="conn->lchan = conn->lchan_for_assignment"];</span><br><span style="color: hsl(120, 100%, 40%);">+   --- [label="IF: chan_mode a speech mode?"];</span><br><span>        bsc_gscon abox bsc_gscon [label="ST_WAIT_MDCX_BTS"];</span><br><span>       bsc_gscon -> bsc_mgcp [label="mgcp_conn_modify()"];</span><br><span>     bsc_mgcp note bsc_mgcp [label="same mgcp FSM as above, for BTS side"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc_mgcp => mgw [label="MDCX (for BTS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc_mgcp <= mgw [label="MDCX OK"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_mgcp abox bsc_mgcp [label="ST_MDCX_RESP"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_mgcp => mgw_msc [label="MDCX (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="On Timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon -> bsc_lchan [label="LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon => mgw_msc [label="BSSMAP Clear Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+     --- [label="END: 'On Timeout'"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_mgcp <= mgw_msc [label="MDCX OK"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_mgcp abox bsc_mgcp [label="ST_READY"];</span><br><span>         bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_MDCX_RESP_BTS"];</span><br><span>     bsc_gscon abox bsc_gscon [label="ST_WAIT_CRCX_MSC"];</span><br><span>       bsc_gscon -> bsc_mgcp [label="mgcp_conn_create()"];</span><br><span>     bsc_mgcp note bsc_mgcp [label="second mgcp FSM for MSC side"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc_mgcp => mgw [label="CRCX (for MSC)"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc_mgcp <= mgw [label="CRCX OK (for MSC)"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_mgcp => mgw_msc [label="CRCX (for MSC)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="On Timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon -> bsc_lchan [label="LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon => mgw_msc [label="BSSMAP Clear Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+     --- [label="END: 'On Timeout'"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_mgcp <= mgw_msc [label="CRCX OK (for MSC)"];</span><br><span>        bsc_gscon <- bsc_mgcp [label="GSCON_EV_MGW_CRCX_RESP_MSC"];</span><br><span style="color: hsl(0, 100%, 40%);">-        ---;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="END: chan_mode a speech mode?"];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      bsc_gscon => msc_ [label="BSSMAP Assignment Complete"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon => mgw_msc [label="BSSMAP Assignment Complete"];</span><br><span> </span><br><span>  bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span> }</span><br><span>diff --git a/doc/handover-inter-bsc-mo.msc b/doc/handover-inter-bsc-mo.msc</span><br><span>new file mode 100644</span><br><span>index 0000000..9aff7a7</span><br><span>--- /dev/null</span><br><span>+++ b/doc/handover-inter-bsc-mo.msc</span><br><span>@@ -0,0 +1,37 @@</span><br><span style="color: hsl(120, 100%, 40%);">+msc {</span><br><span style="color: hsl(120, 100%, 40%);">+     hscale=2;</span><br><span style="color: hsl(120, 100%, 40%);">+     ms [label="MS via BTS"], bsc_lchan[label="BSC lchan FSM"], bsc_gscon[label="BSC conn FSM"],</span><br><span style="color: hsl(120, 100%, 40%);">+     msc_[label="MSC"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ms note msc_ [label="inter-BSC Handover to another BSS"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon box bsc_gscon [label="bsc_handover_start(): init conn->ho"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon -> bsc_gscon [label="GSCON_EV_HO_START (inter-BSC MO)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MO_\nWAIT_HO_CMD\nT7"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon => msc_ [label="BSSMAP Handover Required"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="On Timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ms note bsc_gscon [label="MS happily continues on the old lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon box bsc_gscon [label="handover_end(fail)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="END: 'On Timeout'"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon <= msc_ [label="BSSMAP Handover Command"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MO_\nWAIT_CLEAR_CMD\nT8"];</span><br><span style="color: hsl(120, 100%, 40%);">+     ms <= bsc_gscon [label="RR Handover Command"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="On Timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ms note bsc_gscon [label="MS happily continues on the old lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon box bsc_gscon [label="handover_end(fail)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="END: 'On Timeout'"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  msc_ note msc_ [label="Remote BSS reported Handover Complete to the MSC, this connection has been</span><br><span style="color: hsl(120, 100%, 40%);">+                superseded."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon <= msc_ [label="BSSMAP Clear Command"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_CLEARING"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon => msc_ [label="BSSMAP Clear Complete"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan <- bsc_gscon [label="LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       ms <=> bsc_lchan [label="release procedure (async)"];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/doc/handover-inter-bsc-mt.msc b/doc/handover-inter-bsc-mt.msc</span><br><span>new file mode 100644</span><br><span>index 0000000..88a52da</span><br><span>--- /dev/null</span><br><span>+++ b/doc/handover-inter-bsc-mt.msc</span><br><span>@@ -0,0 +1,154 @@</span><br><span style="color: hsl(120, 100%, 40%);">+msc {</span><br><span style="color: hsl(120, 100%, 40%);">+        hscale=3;</span><br><span style="color: hsl(120, 100%, 40%);">+     ms [label="MS via BTS"], bsc_lchan[label="BSC lchan FSM"], bsc_gscon[label="BSC conn FSM"],</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_mgcp[label="BSC mgcp FSM"], mgw_msc[label="MGW/MSC"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ms note mgw_msc [label="inter-BSC Handover, from remote BSS"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon <= mgw_msc [label="N-Connect: BSSMAP Handover Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon box bsc_gscon [label="bsc_subscr_con_allocate()"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_WAIT_LCHAN"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon box bsc_gscon [label="lchan_select_by_chan_mode()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan <- bsc_gscon [label="lchan_activate(lchan, FOR_HANDOVER)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_TS_READY"];</span><br><span style="color: hsl(120, 100%, 40%);">+  ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="on no lchan, lchan FSM error or timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon box bsc_gscon [label="handover_end(fail)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon => mgw_msc [label="BSSMAP Handover Failure"];</span><br><span style="color: hsl(120, 100%, 40%);">+  ms note bsc_gscon [label="MS happily continues on the old lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+ --- [label="END: 'on error'"];</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%);">+        --- [label="IF lchan FSM decides that it is an lchan for speech"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_MGW_ENDPOINT_AVAILABLE"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan -> bsc_gscon [label="GSCON_EV_ENSURE_MGW_ENDPOINT"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_CRCX_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon box bsc_gscon [label="handover_created_mgw_endpoint = true"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon -> bsc_mgcp [label="mgcp_conn_create()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_mgcp => mgw_msc [label="CRCX (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_mgcp abox bsc_mgcp [label="ST_CRCX_RESP (MGCP_MGW_TIMEOUT = 4s)"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon note bsc_mgcp [label="conn FSM relies on mgcp FSM timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="On Timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_mgcp note bsc_mgcp [label="On timeout, the MGCP FSM will terminate, emitting the parent_term</span><br><span style="color: hsl(120, 100%, 40%);">+         event set upon mgcp_conn_create():"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon note bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS is handled by the conn FSM allstate</span><br><span style="color: hsl(120, 100%, 40%);">+               handler. It sets conn->user_plane.fi_bts = NULL."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan note bsc_gscon [label="conn FSM error handler exits and relies on the lchan FSM</span><br><span style="color: hsl(120, 100%, 40%);">+                signalling error, which should actually happen immediately:"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon <- bsc_lchan [label="GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon box bsc_gscon [label="handover_end(fail)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon => mgw_msc [label="BSSMAP Handover Failure"];</span><br><span style="color: hsl(120, 100%, 40%);">+  ms note bsc_gscon [label="MS happily continues on the old lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+ --- [label="END: 'On Timeout'"];</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%);">+        bsc_mgcp <= mgw_msc [label="CRCX OK (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_mgcp box bsc_mgcp [label="libosmo-mgcp-client fsm_crcx_resp_cb()"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_mgcp abox bsc_mgcp [label="ST_READY"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_CRCX_RESP_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_ACTIV_ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon note bsc_gscon [label="MSC-side CRCX needs from Handover Required the RTP IP address</span><br><span style="color: hsl(120, 100%, 40%);">+           and port of the MSC's MGW; from MGW CRCX ACK (BTS) the conn->user_plane.mgw_endpoint; The</span><br><span style="color: hsl(120, 100%, 40%);">+              Call-ID, which we actually derive from the SCCP connection ID"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_WAIT_CRCX_MSC"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon -> bsc_mgcp [label="mgcp_conn_create()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_mgcp note bsc_mgcp [label="second mgcp FSM for MSC side"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_mgcp => mgw_msc [label="CRCX (for MSC)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="On Timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_mgcp note bsc_mgcp [label="On timeout, the MGCP FSM will terminate, emitting the parent_term</span><br><span style="color: hsl(120, 100%, 40%);">+         event set upon mgcp_conn_create():"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_FAIL_MSC"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon note bsc_gscon [label="GSCON_EV_MGW_FAIL_MSC is handled by the conn FSM allstate</span><br><span style="color: hsl(120, 100%, 40%);">+               handler. It sets conn->user_plane.fi_msc = NULL."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon -> bsc_lchan [label="LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete() (FSM for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon box bsc_gscon [label="handover_end(fail)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon => mgw_msc [label="BSSMAP Handover Failure"];</span><br><span style="color: hsl(120, 100%, 40%);">+  ms note bsc_gscon [label="MS happily continues on the old lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+ --- [label="END: 'On Timeout'"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_mgcp <= mgw_msc [label="CRCX OK (for MSC)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon <- bsc_mgcp [label="GSCON_EV_MGW_CRCX_RESP_MSC"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_WAIT_LCHAN"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="END: chan_mode a speech mode?"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="END: lchan FSM decides that it is an lchan for speech"];</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%);">+        bsc_lchan note bsc_lchan [label="TODO: when does the MS send RLL Establish Ind? I guess like</span><br><span style="color: hsl(120, 100%, 40%);">+             this:"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_RLL_ESTABLISH"];</span><br><span style="color: hsl(120, 100%, 40%);">+     ms => bsc_lchan [label="RLL Establish Ind"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_\nWAIT_HO_ACCEPT\nsanity timer?"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon box bsc_gscon [label="Compose RR Handover Command"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon => mgw_msc [label="BSSMAP Handover Request Acknowledge"];</span><br><span style="color: hsl(120, 100%, 40%);">+      mgw_msc note mgw_msc [label="MSC forwards the RR HO Cmd to the remote BSS"];</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%);">+  --- [label="On timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan <- bsc_gscon [label="NEW lchan: LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ms <=> bsc_lchan [label="release procedure (async)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon box bsc_gscon [label="handover_end(fail)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon => mgw_msc [label="BSSMAP Clear Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ms note bsc_gscon [label="MS happily continues on the old lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+ --- [label="END: On timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  ms => bsc_gscon [label="RR Handover Accept"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon => mgw_msc [label="BSSMAP Handover Detect"];</span><br><span style="color: hsl(120, 100%, 40%);">+   mgw_msc note mgw_msc [label="MSC switches call to new path"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_WAIT_SABM\nT3105"];</span><br><span style="color: hsl(120, 100%, 40%);">+ ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  ms => bsc_gscon [label="SABM"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan note bsc_lchan [label="SABM: Layer 2 message containing ?"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_\nWAIT_MDCX_BTS\nT?"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan note bsc_lchan [label="TODO: what is UA?"];</span><br><span style="color: hsl(120, 100%, 40%);">+       ms <= bsc_gscon [label="RR UA"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon note bsc_gscon [label="TODO: at what point do we know the information needed for BTS</span><br><span style="color: hsl(120, 100%, 40%);">+           MDCX?"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon -> bsc_mgcp [label="mgcp_conn_modify()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_mgcp abox bsc_mgcp [label="ST_MDCX_RESP"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_mgcp => mgw_msc [label="MDCX (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="Should the Handover Complete arrive early"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ms => bsc_gscon [label="RR Handover Complete"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon box bsc_gscon [label="handover_complete_received = true"];</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%);">+  --- [label="On timeout of the mgcp FSM"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon note mgw_msc [label="MGCP FSM terminates"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon <- bsc_mgcp [label="GSCON_EV_MGW_FAIL_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan note bsc_gscon [label="The phone has already taken on the new lchan, but now we happen</span><br><span style="color: hsl(120, 100%, 40%);">+         to not be able to use it. The only sensible thing is to end the conn."];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon => mgw_msc [label="BSSMAP Clear Request\n(Equipment Failure)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan <- bsc_gscon [label="NEW lchan: LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ms <=> bsc_lchan [label="release procedure (async)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      --- [label="END: On timeout of the mgcp FSM"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_mgcp <= mgw_msc [label="MDCX OK"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_mgcp abox bsc_mgcp [label="ST_READY"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_MDCX_RESP_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+      --- [label="IF !handover_complete_received"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_WAIT_HO_COMPL\nT?"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="ELSE"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon -> bsc_gscon [label="gscon_handover_post_complete()"];</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%);">+  ms => bsc_gscon [label="RR Handover Complete"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon box bsc_gscon [label="gscon_handover_post_complete()"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon => mgw_msc [label="BSSMAP Handover Complete"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon note bsc_gscon [label="handover_end(success), conn->ho = NULL"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/doc/handover.msc b/doc/handover.msc</span><br><span>index 8862dd9..7529de6 100644</span><br><span>--- a/doc/handover.msc</span><br><span>+++ b/doc/handover.msc</span><br><span>@@ -1,170 +1,123 @@</span><br><span> # Handover between cells, intra-BSC</span><br><span> msc {</span><br><span>        hscale=3;</span><br><span style="color: hsl(0, 100%, 40%);">-       ms [label="MS"], bts [label="BTS"], bsc[label="BSC"], bsc_gscon[label="BSC conn FSM"], bsc_mgcp[label="BSC mgcp FSM"], mgw[label="MGW"];</span><br><span style="color: hsl(120, 100%, 40%);">+  ms [label="MS via BTS"], bsc_lchan[label="BSC lchan FSM"], bsc_gscon[label="BSC conn FSM"],</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_mgcp[label="BSC mgcp FSM"], mgw_msc[label="MGW/MSC"];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       ms note mgw [label="intra-BSC Handover sequence"];</span><br><span style="color: hsl(120, 100%, 40%);">+  ms note mgw_msc [label="intra-BSC Handover sequence"];</span><br><span> </span><br><span>         bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="bsc_handover_start(): init conn->ho"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc -> bsc_gscon [label="GSCON_EV_HO_START"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc <- bsc_gscon [label="bsc_handover_start_gscon()"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc box bsc [label="lchan_alloc(): pick available lchan"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="rsl_chan_activate_lchan()"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      --- [label="is the chosen lchan on dynamic timeslot that is currently used as PDCH?"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bts <= bsc [label="i) RSL RF Chan Release of PDCH (Osmocom dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bts <= bsc [label="OR ii) RSL PDCH Deact (ip.access dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc -> bsc_gscon [label="bsc_handover_start_gscon() returns early"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc_gscon abox bsc_gscon [label="ST_WAIT_HO_COMPL (no timeout, relies on T3103 below)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon box bsc_gscon [label="bsc_handover_start(): init conn->ho"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon -> bsc_gscon [label="GSCON_EV_HO_START (intra-BSC)"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_LCHAN"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan <- bsc_gscon [label="lchan_activate(lchan, FOR_HANDOVER)"];</span><br><span>   ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-          label="Osmocom style dyn TS use lchan->act_timer to watch over RF Chan Release, but there</span><br><span style="color: hsl(0, 100%, 40%);">-               seems to be no timer watching over PDCH Deact!"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="on lchan FSM error or timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon box bsc_gscon [label="handover_end(fail)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       ms note bsc_gscon [label="MS happily continues on the old lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="END: 'on error'"];</span><br><span>     ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="i) RSL RF Chan Release ACK (Osmocom dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bts => bsc [label="OR ii) RSL PDCH Deact ACK (ip.access dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="rsl_chan_activate_lchan() re-invoked"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts <= bsc [label="RSL Chan Activ"];</span><br><span style="color: hsl(0, 100%, 40%);">-       --- [label="else (no dyn TS switchover)"];</span><br><span style="color: hsl(120, 100%, 40%);">+  ...;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        bts <= bsc [label="RSL Chan Activ"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc -> bsc_gscon [label="bsc_handover_start_gscon() returns"];</span><br><span style="color: hsl(120, 100%, 40%);">+   --- [label="IF lchan FSM decides that it is an lchan for speech"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan -> bsc_gscon [label="GSCON_EV_ENSURE_MGW_ENDPOINT"];</span><br><span style="color: hsl(120, 100%, 40%);">+   --- [label="IF there is an MGW endpoint for the BTS already (conn->user_plane.fi_bts)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon box bsc_gscon [label="handover_created_mgw_endpoint = false"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="ELSE: no MGW endpoint for the BTS side yet"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_CRCX_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon box bsc_gscon [label="handover_created_mgw_endpoint = true"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon -> bsc_mgcp [label="mgcp_conn_create()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_mgcp => mgw_msc [label="CRCX (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_mgcp abox bsc_mgcp [label="ST_CRCX_RESP (MGCP_MGW_TIMEOUT = 4s)"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon note bsc_mgcp [label="conn FSM relies on mgcp FSM timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="On Timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_mgcp note bsc_mgcp [label="On timeout, the MGCP FSM will terminate, emitting the parent_term</span><br><span style="color: hsl(120, 100%, 40%);">+         event set upon mgcp_conn_create():"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon note bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS is handled by the conn FSM allstate</span><br><span style="color: hsl(120, 100%, 40%);">+               handler. It sets conn->user_plane.fi_bts = NULL."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan note bsc_gscon [label="conn FSM error handler exits and relies on the lchan FSM</span><br><span style="color: hsl(120, 100%, 40%);">+                signalling error, which should actually happen immediately:"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon <- bsc_lchan [label="GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon box bsc_gscon [label="handover_end(fail)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="IF handover_created_mgw_endpoint == true"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];</span><br><span>     ---;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc_gscon abox bsc_gscon [label="ST_WAIT_HO_COMPL (no timeout, relies on T3103 below)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ms note bsc_gscon [label="MS happily continues on the old lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="END: 'On Timeout'"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_mgcp <= mgw_msc [label="CRCX OK (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_mgcp box bsc_mgcp [label="libosmo-mgcp-client fsm_crcx_resp_cb()"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_mgcp abox bsc_mgcp [label="ST_READY"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_CRCX_RESP_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_LCHAN"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="END: lchan FSM decides that it is an lchan for speech"];</span><br><span>       ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-    label="There seems to be no timer watching out for RSL Chan Activ ACK/NACK!"];</span><br><span>   ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="RSL Chan Activ ACK"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="rsl_rx_chan_act_ack()"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc box bsc [label="Stop lchan->act_timer"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="lchan->state = LCHAN_S_ACTIVE"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc -> bsc [label="S_LCHAN_ACTIVATE_ACK"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="handover_logic.c ho_logic_sig_cb()"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc box bsc [label="ho_chan_activ_ack()"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc note bsc [label="gsm48_send_ho_cmd()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   ms <= bsc [label="RR Handover Command"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc abox bsc [label="start T3103"];</span><br><span style="color: hsl(0, 100%, 40%);">-   --- [label="is BTS using IPA Abis? (osmo-bts, ip.access)"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts <= bsc [label="IPACC CRCX"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc -> bsc [label="ho_chan_activ_ack() returns"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bts note bsc [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-          label="There seems to be no timer watching over IPACC CRCX ACK/NACK!</span><br><span style="color: hsl(0, 100%, 40%);">-              If no response is received, we simply ignore that fact and carry on as if</span><br><span style="color: hsl(0, 100%, 40%);">-               everything was fine."];</span><br><span style="color: hsl(0, 100%, 40%);">-   ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts note bsc [label="The IPACC CRCX and MDCX ACKs may come back at any time:</span><br><span style="color: hsl(0, 100%, 40%);">-                            before or after the Handover Detect, before or after Handover Complete."];</span><br><span style="color: hsl(0, 100%, 40%);">-    bts note bsc_mgcp [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-     label="The CRCX ACK contains vital information for routing the RTP stream.</span><br><span style="color: hsl(0, 100%, 40%);">-                If the CRCX ACK were very slow, we would not know which RTP/RTPC ports</span><br><span style="color: hsl(0, 100%, 40%);">-          to point the MGW at, below at mgcp_conn_modify()!</span><br><span style="color: hsl(0, 100%, 40%);">-               Even though this being unrealistic, we must make sure to receive a CRCX ACK."];</span><br><span style="color: hsl(0, 100%, 40%);">-   ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="osmo_bsc_audio.c"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bts => bsc [label="IPACC CRCX ACK"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bts <= bsc [label="IPACC MDCX"];</span><br><span style="color: hsl(0, 100%, 40%);">-   ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts note bsc [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-          label="There seems to be no timer watching over IPACC MDCX ACK/NACK!</span><br><span style="color: hsl(0, 100%, 40%);">-              If no response is received, we simply ignore that fact and carry on as if</span><br><span style="color: hsl(0, 100%, 40%);">-               everything was fine."];</span><br><span style="color: hsl(0, 100%, 40%);">-   ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="IPACC MDCX ACK"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bts note bsc [label="IPACC MDCX ACK triggers no events or actions"];</span><br><span style="color: hsl(0, 100%, 40%);">-  ---;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    ms => bsc [label="RR Handover Detect"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc -> bsc [label="S_LCHAN_HANDOVER_DETECT"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc box bsc [label="ho_rsl_detect(): no action, only logging"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc note bsc_gscon [label="Handover Detect triggers no events or actions"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-    label="upon Handover Detect, we should already start re-routing the RTP!</span><br><span style="color: hsl(0, 100%, 40%);">-          Instead we wait for Handover Complete."];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_DETECT\nT3103"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon box bsc_gscon [label="gsm48_send_ho_cmd()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ms <= bsc_gscon [label="RR Handover Command"];</span><br><span> </span><br><span>      ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    ms => bsc [label="RR Handover Complete"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc -> bsc [label="S_LCHAN_HANDOVER_COMPL"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="handover_logic.c ho_logic_sig_cb()"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc box bsc [label="ho_gsm48_ho_compl()"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="stop T3103"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bts note bsc_gscon [label="If anything goes wrong from this point on, we will not move back</span><br><span style="color: hsl(0, 100%, 40%);">-                                   to the old lchan: would be pointless after Handover Complete."];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc note bsc [label="officially take over new lchan: conn->lchan = ho->new_lchan"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     --- [label="Release old lchan"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc box bsc [label="_lchan_handle_release(sacch_deact=0)"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="rsl_release_sapis_from(start=1)"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bts <= bsc [label="RSL Release Request (Local End)..."];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts <= bsc [label="...for each SAPI except link_id=0"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="rsl_release_request(link_id=0)"];</span><br><span style="color: hsl(0, 100%, 40%);">- bts <= bsc [label="RSL Release Request (Local End) for link_id=0"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="_lchan_handle_release() returns here, the remaining release is asynchronous;</span><br><span style="color: hsl(0, 100%, 40%);">-                       see `End: 'Release old lchan'` below."];</span><br><span style="color: hsl(0, 100%, 40%);">-       ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-    label="There seems to be no timer watching over RSL Release Request!"];</span><br><span style="color: hsl(0, 100%, 40%);">-     ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="RSL Release Confirm..."];</span><br><span style="color: hsl(0, 100%, 40%);">-       bts => bsc [label="...for each SAPI and link_id=0"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc abox bsc [label="start T3111"];</span><br><span style="color: hsl(0, 100%, 40%);">-   ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="T3111 expires"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc abox bsc [label="Start lchan->act_timer with lchan_deact_tmr_cb"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bts <= bsc [label="RSL RF Channel Release"];</span><br><span style="color: hsl(0, 100%, 40%);">-       ...;</span><br><span>         --- [label="On timeout"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc box bsc [label="lchan_deact_tmr_cb()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="rsl_lchan_mark_broken(): state=LCHAN_S_BROKEN"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc box bsc [label="lchan_free()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc -> bsc [label="S_LCHAN_UNEXPECTED_RELEASE"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="bsc_api.c handle_release()"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc box bsc [label="bsc->clear_request()"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="bsc_clear_request encodes a BSSMAP Clear Request message and passes it on</span><br><span style="color: hsl(0, 100%, 40%);">-                          to the conn FSM as data argument via:"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc -> bsc_gscon [label="GSCON_EV_TX_SCCP"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc_gscon rbox bsc_gscon [label="BSSMAP Clear Request to MSC"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-    label="During Handover, we actually release the entire conn just because we failed to</span><br><span style="color: hsl(0, 100%, 40%);">-             gracefully release the old lchan. That is obviously nonsense."];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc note bsc [label="Stop T3101 (but was not active in this code path)"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc -> bsc [label="S_CHALLOC_FREED"];</span><br><span style="color: hsl(0, 100%, 40%);">-      --- [label="End: 'On timeout'"];</span><br><span style="color: hsl(0, 100%, 40%);">-      ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="RSL RF Channel Release Ack"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="Stop lchan->act_timer"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="Stop lchan->T3111"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan <- bsc_gscon [label="NEW lchan: LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ms <=> bsc_lchan [label="release procedure (async)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon box bsc_gscon [label="handover_end(fail)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="IF handover_created_mgw_endpoint == true"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];</span><br><span>     ---;</span><br><span style="color: hsl(120, 100%, 40%);">+  ms note bsc_gscon [label="MS happily continues on the old lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="END: On timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  ms => bsc_gscon [label="RR Handover Detect"];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  bsc box bsc [label="still in ho_gsm48_ho_compl()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc note bsc [label="handover_free(), conn->ho = NULL"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc -> bsc_gscon [label="GSCON_EV_HO_COMPL"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc note bsc_gscon [linecolor="orange",</span><br><span style="color: hsl(0, 100%, 40%);">-         label="Handover information is cleared before signalling the conn FSM.</span><br><span style="color: hsl(0, 100%, 40%);">-            That means the conn FSM cannot possibly log sensible information about exactly</span><br><span style="color: hsl(0, 100%, 40%);">-          which Handover has just completed."];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc_gscon abox bsc_gscon [label="ST_WAIT_MDCX_BTS_HO</span><br><span style="color: hsl(0, 100%, 40%);">-                                        (MGCP_MGW_TIMEOUT=4s with MGCP_MGW_HO_TIMEOUT_TIMER_NR)"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_MDCX_BTS\ncontinue T3103"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon -> bsc_lchan [label="OLD lchan: LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ms <=> bsc_lchan [label="release procedure (async)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan note bsc_gscon [label="officially take over new lchan: conn->lchan = ho->new_lchan"];</span><br><span>      bsc_gscon -> bsc_mgcp [label="mgcp_conn_modify()"];</span><br><span>     bsc_mgcp note bsc_mgcp [label="mgcp FSM that was established for old lchan, for BTS side"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc_mgcp => mgw [label="MDCX (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_mgcp abox bsc_mgcp [label="ST_MDCX_RESP"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_mgcp => mgw_msc [label="MDCX (for BTS)"];</span><br><span>   ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc_gscon note mgw [</span><br><span style="color: hsl(0, 100%, 40%);">-      label="If we get no MDCX ACK, the MGCP FSM terminates, and emits GSCON_EV_MGW_FAIL_BTS.</span><br><span style="color: hsl(0, 100%, 40%);">-           Besides invalidating the MGCP FSM pointer, this event has no</span><br><span style="color: hsl(0, 100%, 40%);">-            effect in ST_WAIT_MDCX_BTS_HO, and we rely on above conn FSM</span><br><span style="color: hsl(0, 100%, 40%);">-            timeout instead."];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc_gscon note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-      label="A timeout of ST_WAIT_MDCX_BTS_HO simply transitions back to ST_ACTIVE!</span><br><span style="color: hsl(0, 100%, 40%);">-             Even though the MGW failed, we carry on as if everything were fine."];</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="Should the Handover Complete arrive early"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ms => bsc_gscon [label="RR Handover Complete"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon box bsc_gscon [label="handover_complete_received = true"];</span><br><span style="color: hsl(120, 100%, 40%);">+        ---;</span><br><span>         ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc_mgcp <= mgw [label="MDCX OK"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="On timeout of the mgcp FSM"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon note mgw_msc [label="MGCP FSM terminates"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon <- bsc_mgcp [label="GSCON_EV_MGW_FAIL_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan note bsc_gscon [label="The phone has already taken on the new lchan, but now we happen</span><br><span style="color: hsl(120, 100%, 40%);">+         to not be able to use it. The only sensible thing is to end the conn."];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon => mgw_msc [label="BSSMAP Clear Request\n(Equipment Failure)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan <- bsc_gscon [label="NEW lchan: LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ms <=> bsc_lchan [label="release procedure (async)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_mgcp <= mgw_msc [label="MDCX OK"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_mgcp abox bsc_mgcp [label="ST_READY"];</span><br><span>         bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_MDCX_RESP_BTS"];</span><br><span style="color: hsl(120, 100%, 40%);">+      --- [label="IF !handover_complete_received"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_COMPLETE\ncontinue T3103"];</span><br><span style="color: hsl(120, 100%, 40%);">+     --- [label="ELSE"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon -> bsc_gscon [label="gscon_handover_post_complete()"];</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%);">+  ms => bsc_gscon [label="RR Handover Complete"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon box bsc_gscon [label="gscon_handover_post_complete()"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon note bsc_gscon [label="handover_end(success), conn->ho = NULL"];</span><br><span>      bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span> }</span><br><span>diff --git a/doc/lchan-fsm.dot b/doc/lchan-fsm.dot</span><br><span>new file mode 100644</span><br><span>index 0000000..dbb283c</span><br><span>--- /dev/null</span><br><span>+++ b/doc/lchan-fsm.dot</span><br><span>@@ -0,0 +1,53 @@</span><br><span style="color: hsl(120, 100%, 40%);">+digraph G {</span><br><span style="color: hsl(120, 100%, 40%);">+rankdir=TB;</span><br><span style="color: hsl(120, 100%, 40%);">+      </span><br><span style="color: hsl(120, 100%, 40%);">+      invisible [style="invisible"]</span><br><span style="color: hsl(120, 100%, 40%);">+       UNUSED [penwidth=3.0]</span><br><span style="color: hsl(120, 100%, 40%);">+ WAIT_TS_READY</span><br><span style="color: hsl(120, 100%, 40%);">+ WAIT_MGW_ENDPOINT_AVAILABLE</span><br><span style="color: hsl(120, 100%, 40%);">+   WAIT_ACTIV_ACK</span><br><span style="color: hsl(120, 100%, 40%);">+        WAIT_IPACC_CRCX_ACK</span><br><span style="color: hsl(120, 100%, 40%);">+   WAIT_IPACC_MDCX_ACK</span><br><span style="color: hsl(120, 100%, 40%);">+   WAIT_RLL_ESTABLISH</span><br><span style="color: hsl(120, 100%, 40%);">+    ACTIVE [penwidth=3.0]</span><br><span style="color: hsl(120, 100%, 40%);">+ WAIT_SAPIS_RELEASED</span><br><span style="color: hsl(120, 100%, 40%);">+   WAIT_BEFORE_RF_RELEASE</span><br><span style="color: hsl(120, 100%, 40%);">+        WAIT_RF_RELEASE_ACK</span><br><span style="color: hsl(120, 100%, 40%);">+   WAIT_AFTER_ERROR</span><br><span style="color: hsl(120, 100%, 40%);">+      BORKEN</span><br><span style="color: hsl(120, 100%, 40%);">+        </span><br><span style="color: hsl(120, 100%, 40%);">+      ts [label="timeslot FSM",shape=box3d];</span><br><span style="color: hsl(120, 100%, 40%);">+      gscon [label="conn FSM",shape=box3d];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     UNUSED -> WAIT_TS_READY [label="lchan_allocate()"]</span><br><span style="color: hsl(120, 100%, 40%);">+       WAIT_TS_READY -> WAIT_ACTIV_ACK</span><br><span style="color: hsl(120, 100%, 40%);">+    WAIT_ACTIV_ACK -> WAIT_RLL_ESTABLISH</span><br><span style="color: hsl(120, 100%, 40%);">+       WAIT_RLL_ESTABLISH -> WAIT_MGW_ENDPOINT_AVAILABLE [label="TCH"]</span><br><span style="color: hsl(120, 100%, 40%);">+  WAIT_MGW_ENDPOINT_AVAILABLE -> WAIT_IPACC_CRCX_ACK [label="IPACC BTS"]</span><br><span style="color: hsl(120, 100%, 40%);">+   WAIT_MGW_ENDPOINT_AVAILABLE -> ACTIVE</span><br><span style="color: hsl(120, 100%, 40%);">+      WAIT_IPACC_CRCX_ACK -> WAIT_IPACC_MDCX_ACK</span><br><span style="color: hsl(120, 100%, 40%);">+ WAIT_IPACC_MDCX_ACK -> ACTIVE</span><br><span style="color: hsl(120, 100%, 40%);">+      WAIT_RLL_ESTABLISH -> ACTIVE [label="non-TCH"];</span><br><span style="color: hsl(120, 100%, 40%);">+  WAIT_RLL_ESTABLISH -> WAIT_RF_RELEASE_ACK [label="timeout",style=dashed,constraint=false]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      ACTIVE -> WAIT_SAPIS_RELEASED [label="LCHAN_EV_\nRELEASE"]</span><br><span style="color: hsl(120, 100%, 40%);">+       WAIT_SAPIS_RELEASED -> WAIT_BEFORE_RF_RELEASE</span><br><span style="color: hsl(120, 100%, 40%);">+      WAIT_SAPIS_RELEASED -> WAIT_RF_RELEASE_ACK [label="timeout",style=dashed,constraint=false]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     WAIT_BEFORE_RF_RELEASE -> WAIT_RF_RELEASE_ACK [label="T3111"]</span><br><span style="color: hsl(120, 100%, 40%);">+    WAIT_RF_RELEASE_ACK -> UNUSED</span><br><span style="color: hsl(120, 100%, 40%);">+      WAIT_RF_RELEASE_ACK -> WAIT_AFTER_ERROR [label="release was\ndue to error"]</span><br><span style="color: hsl(120, 100%, 40%);">+      WAIT_AFTER_ERROR -> UNUSED [label="T3111+2s"]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  WAIT_TS_READY -> ts [label="TS_EV_\nLCHAN_\nREQUESTED",style=dotted,penwidth=3]</span><br><span style="color: hsl(120, 100%, 40%);">+  UNUSED -> ts [label="TS_EV_\nLCHAN_\nUNUSED",style=dotted,penwidth=3]</span><br><span style="color: hsl(120, 100%, 40%);">+    ts -> WAIT_TS_READY [label="LCHAN_EV_\nTS_READY",style=dotted]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ WAIT_TS_READY -> UNUSED [label="error/timeout",style=dashed,constraint=false]</span><br><span style="color: hsl(120, 100%, 40%);">+    {WAIT_ACTIV_ACK,WAIT_RF_RELEASE_ACK} -> BORKEN [label="error/timeout",style=dashed]</span><br><span style="color: hsl(120, 100%, 40%);">+      {WAIT_MGW_ENDPOINT_AVAILABLE,WAIT_IPACC_CRCX_ACK,WAIT_IPACC_MDCX_ACK} -> WAIT_SAPIS_RELEASED [label=error,style=dashed]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  WAIT_TS_READY -> gscon [label="GSCON_EV_\nENSURE_\nMGW_ENDPOINT",style=dotted]</span><br><span style="color: hsl(120, 100%, 40%);">+   gscon -> WAIT_MGW_ENDPOINT_AVAILABLE [label="LCHAN_EV_\nMGW_ENDPOINT_\n{AVAILABLE,ERROR}",style=dotted]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/doc/lchan-release.msc b/doc/lchan-release.msc</span><br><span>index f75b559..017c9cf 100644</span><br><span>--- a/doc/lchan-release.msc</span><br><span>+++ b/doc/lchan-release.msc</span><br><span>@@ -1,149 +1,83 @@</span><br><span> msc {</span><br><span>     hscale=2;</span><br><span style="color: hsl(0, 100%, 40%);">-       ms [label="MS"], bts [label="BTS"], bsc[label="BSC"], bsc_gscon[label="BSC conn FSM"];</span><br><span style="color: hsl(120, 100%, 40%);">+        ms [label="MS"], bts [label="BTS"], bsc[label="BSC"], bsc_lchan[label="BSC lchan FSM"],</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon[label="BSC conn FSM"], msc_[label="MSC"];</span><br><span> </span><br><span>  ms note bsc_gscon [label="various lchan release scenarios"];</span><br><span>       </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        ms rbox bsc_gscon [label="IF BSC releases, from BSSMAP Clear Request"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc note bsc [label="lchan_release() may be called with sacch_deact=true or false.</span><br><span style="color: hsl(0, 100%, 40%);">-         Currently, the only time lchan_release(sacch_deact=true) is invoked is upon BSSMAP Clear</span><br><span style="color: hsl(0, 100%, 40%);">-                Command, i.e. when the MSC instructs to stop using an active lchan.</span><br><span style="color: hsl(0, 100%, 40%);">-             Some error handling code paths however directly invoke</span><br><span style="color: hsl(0, 100%, 40%);">-          rsl_rf_chan_release(error=1, SACCH_DEACTIVATE)."];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ---;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc_gscon note bsc_gscon [label="Rx: BSSMAP Clear Request from MSC"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc <- bsc_gscon [label="gsm0808_clear()"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="lchan_release(sacch_deact=1)"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="lchan->state = LCHAN_S_REL_REQ"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc box bsc [label="_lchan_handle_release(sacch_deact=1)"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="rsl_release_sapis_from(start=1)"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bts <= bsc [label="RSL Release Request (Local End)..."];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts <= bsc [label="...for each SAPI, except link_id=0"];</span><br><span style="color: hsl(0, 100%, 40%);">-   ms <= bsc [label="RR Channel Release"];</span><br><span style="color: hsl(0, 100%, 40%);">-    ms note bsc [label="There is no ACK for RR Channel Release"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="rsl_deact_sacch()"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bts <= bsc [label="RSL Deactivate SACCH"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc abox bsc [label="Start T3109 (net->T3109, t3109_expired())"];</span><br><span style="color: hsl(120, 100%, 40%);">+        ms rbox msc_ [label="MSC releases"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon <= msc_ [label="BSSMAP Clear Command"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_CLEARING"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon => msc_ [label="BSSMAP Clear Complete"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_gscon -> bsc_lchan [label="LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="IF SAPIs besides SAPI[0] are active"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nSAPIS_RELEASED\nT3109"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts <= bsc_lchan [label="RSL Release Request (Local End)..."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts <= bsc_lchan [label="...for each SAPI, except link_id=0"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ms <= bsc_lchan [label="RR Channel Release"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bts <= bsc_lchan [label="RSL Deactivate SACCH",ID="if appropriate pchan"];</span><br><span>    ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    --- [label="If T3109 expires"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="t3109_expired()"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="rsl_rf_chan_release(error=1)"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts <= bsc [label="RSL Release Request (Local End)..."];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts <= bsc [label="...for each SAPI, except link_id=0"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="lchan->state = LCHAN_S_REL_REQ"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bts <= bsc [label="RSL RF Channel Release"];</span><br><span style="color: hsl(0, 100%, 40%);">-       ---;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts => bsc_lchan [label="RSL Release ACKs"];</span><br><span style="color: hsl(120, 100%, 40%);">+     --- [label="END: SAPIs besides SAPI[0] are active"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nBEFORE_RF_RELEASE\nT3111"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan -> bsc_gscon [label="GSCON_EV_FORGET_LCHAN"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon note bsc_gscon [label="has already forgotten the lchan above."];</span><br><span>         ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc rbox bsc [label="continue in the 'Common' part"];</span><br><span style="color: hsl(0, 100%, 40%);">- --- [label="END: 'BSSMAP Clear Request'"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRF_RELEASE_ACK\n4s"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bts <= bsc_lchan [label="RSL RF Channel Release"];</span><br><span style="color: hsl(120, 100%, 40%);">+       ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts => bsc_lchan [label="RSL RF Channel Release ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];</span><br><span>        ...;</span><br><span>         ...;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        ms rbox bsc_gscon [label="IF BSC releases, from implicitly unused lchan"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc note bsc [label="The BSC may release old unused lchans after Handover, or release lchans</span><br><span style="color: hsl(0, 100%, 40%);">-               after some error condition."];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc note bsc [label="BSC decides to release an unused lchan"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="lchan_release(sacch_deact=0)"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="lchan->state = LCHAN_S_REL_REQ"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc box bsc [label="_lchan_handle_release(sacch_deact=0)"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts <= bsc [label="RSL Release Request (Local End)..."];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts <= bsc [label="...for all SAPIs"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ms rbox msc_ [label="BSC releases, outside of conn FSM's flow"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc -> bsc_lchan [label="LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+     --- [label="IF SAPIs besides SAPI[0] are active"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nSAPIS_RELEASED\nT3109"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts <= bsc_lchan [label="RSL Release Request (Local End)..."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts <= bsc_lchan [label="...for each SAPI, except link_id=0"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ms <= bsc_lchan [label="RR Channel Release",ID="if conn is present"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bts <= bsc_lchan [label="RSL Deactivate SACCH",ID="if appropriate pchan"];</span><br><span>    ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-    label="There seems to be no timer watching over RSL Release Request!"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts => bsc_lchan [label="RSL Release ACKs"];</span><br><span style="color: hsl(120, 100%, 40%);">+     --- [label="END: SAPIs besides SAPI[0] are active"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nBEFORE_RF_RELEASE\nT3111"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan -> bsc_gscon [label="GSCON_EV_FORGET_LCHAN"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon note bsc_gscon [label="conn FSM notices that its primary lchan is gone"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon => msc_ [label="BSSMAP Clear Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];</span><br><span>      ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="RSL Release Confirm..."];</span><br><span style="color: hsl(0, 100%, 40%);">-       bts => bsc [label="...for all SAPIs"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc rbox bsc [label="continue in the 'Common' part"];</span><br><span style="color: hsl(0, 100%, 40%);">- ---;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRF_RELEASE_ACK\n4s"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bts <= bsc_lchan [label="RSL RF Channel Release"];</span><br><span style="color: hsl(120, 100%, 40%);">+       ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts => bsc_lchan [label="RSL RF Channel Release ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+ ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon <= msc_ [label="BSSMAP Clear Command"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_CLEARING"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon => msc_ [label="BSSMAP Clear Complete"];</span><br><span>      ...;</span><br><span>         ...;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        ms rbox bsc_gscon [label="IF MS releases"];</span><br><span style="color: hsl(120, 100%, 40%);">+ ms rbox msc_ [label="MS releases"];</span><br><span>        ms => bts [label="DISC"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bts => bsc [label="RLL Release Ind..."];</span><br><span style="color: hsl(0, 100%, 40%);">-   bts => bsc [label="...for each SAPI"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc rbox bsc [label="continue in the 'Common' part"];</span><br><span style="color: hsl(0, 100%, 40%);">- ---;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts => bsc_lchan [label="RLL Release Ind..."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts => bsc_lchan [label="...for each SAPI"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan note bsc_lchan [label="The lchan FSM notices when all SAPIs have been released"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nBEFORE_RF_RELEASE\nT3111"];</span><br><span>       ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRF_RELEASE_ACK\n4s"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bts <= bsc_lchan [label="RSL RF Channel Release"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan -> bsc_gscon [label="GSCON_EV_FORGET_LCHAN"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon note bsc_gscon [label="conn FSM notices that its primary lchan is gone"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon => msc_ [label="BSSMAP Clear Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];</span><br><span>      ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    ms rbox bsc_gscon [label="Common"];</span><br><span style="color: hsl(0, 100%, 40%);">-   --- [label="for each SAPI (?)"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bts => bsc [label="RLL Release Confirm / RLL Release Ind"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="abis_rsl_rx_rll()"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc box bsc [label="mark lchan->sapis[link_id] = LCHAN_SAPI_UNUSED"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc box bsc [label="rll_indication()"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="for each bsc_rll_req matching this link_id:</span><br><span style="color: hsl(0, 100%, 40%);">-            disable timer, call cb(BSC_RLLR_IND_REL_IND)"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="rsl_handle_release()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   --- [label="IF all SAPIs are unused"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="Stop T3109"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc note bsc [label="T3109 was started if the MSC requested the release"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc abox bsc [label="Start T3111 (net->T3111 value, t3111_expired())"];</span><br><span style="color: hsl(0, 100%, 40%);">-    --- [label="END: all SAPIs are unused"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc -> bsc_gscon [label="GSCON_EV_RLL_REL_IND (only if RLL Release Ind)"];</span><br><span style="color: hsl(0, 100%, 40%);">- --- [label="END: for each SAPI"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+   bts => bsc_lchan [label="RSL RF Channel Release ACK"];</span><br><span>  ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="T3111 expires"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc box bsc [label="rsl_rf_chan_release()"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc box bsc [label="Stop T3109"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc note bsc [label="[If lchan->state is LCHAN_S_REL_ERR, don't do anything]"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc abox bsc [label="Start lchan->act_timer (4s, lchan_deact_tmr_cb())"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bts <= bsc [label="RSL RF Channel Release"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    --- [label="IF lchan->act_timer expires"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="lchan_deact_tmr_cb()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="rsl_lchan_mark_broken(): lchan->state = LCHAN_S_BROKEN"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc box bsc [label="lchan_free() (see below)"];</span><br><span style="color: hsl(0, 100%, 40%);">-       --- [label="END: 'lchan->act_timer expires'"];</span><br><span style="color: hsl(0, 100%, 40%);">-     ...;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="RSL RF Channel Release ACK"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="rsl_rx_rf_chan_rel_ack()"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="Stop lchan->act_timer"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="Stop T3111"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     --- [label="IF lchan->state == LCHAN_S_BROKEN"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc note bsc [label="If an ACK comes in late, for specific BTS models, we may choose to 'repair'</span><br><span style="color: hsl(0, 100%, 40%);">-           the lchan so that it is usable again, by calling do_lchan_free() directly (see below)."];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc box bsc [label="rsl_rx_rf_chan_rel_ack() exits here and none of below actions happen.</span><br><span style="color: hsl(0, 100%, 40%);">-          The lchan remains LCHAN_S_BROKEN indefinitely."];</span><br><span style="color: hsl(0, 100%, 40%);">-  --- [label="END: lchan->state == LCHAN_S_BROKEN"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="do_lchan_free()"];</span><br><span style="color: hsl(0, 100%, 40%);">-        --- [label="IF lchan->state == LCHAN_S_REL_ERR"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc note bsc [label="If release failed, we take the lchan back into operation after due</span><br><span style="color: hsl(0, 100%, 40%);">-            timeout"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc abox bsc [label="Start lchan->error_timer (T3111+2, error_timeout_cb())"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc note bsc [label="do_lchan_free() continues, async:"];</span><br><span style="color: hsl(0, 100%, 40%);">-     ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="error_timeout_cb()"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc box bsc [label="lchan->state = LCHAN_S_NONE"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="dyn TS: activate PDCH..."];</span><br><span style="color: hsl(0, 100%, 40%);">-       --- [label="ELSE"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="lchan->state = LCHAN_S_NONE"];</span><br><span style="color: hsl(0, 100%, 40%);">- --- [label="END: lchan->state == LCHAN_S_REL_ERR"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="lchan_free()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   --- [label="IF conn is still associated (and not dyn TS in switchover)"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc -> bsc [label="S_LCHAN_UNEXPECTED_RELEASE"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="handle_release()"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="Stop T10"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc note bsc [linecolor=orange,label="conn->T10 is actually dead code, it is never started.</span><br><span style="color: hsl(0, 100%, 40%);">-             Instead, the conn FSM starts ST_WAIT_ASS_COMPL with a T10 value."];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc -> bsc_gscon [label="GSCON_EV_RR_ASS_FAIL"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc -> bsc_gscon [label="GSCON_EV_TX_SCCP: BSSMAP Clear Request"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="bsc_clear_handover()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="Stop T3103"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc box bsc [label="free handover struct"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="lchan->conn = NULL"];</span><br><span style="color: hsl(0, 100%, 40%);">-  --- [label="END: 'conn is still associated'"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [label="Stop T3101"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc note bsc [label="T3101 is started when sending an RR Immediate Assignment"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc -> bsc [label="S_CHALLOC_FREED"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bsc -> bsc [label="rll_lchan_signal()"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="for each bsc_rll_req matching this lchan:</span><br><span style="color: hsl(0, 100%, 40%);">-              disable timer, call cb(BSC_RLLR_IND_REL_IND)"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon <= msc_ [label="BSSMAP Clear Command"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon => msc_ [label="BSSMAP Clear Complete"];</span><br><span> }</span><br><span>diff --git a/doc/lchan.msc b/doc/lchan.msc</span><br><span>new file mode 100644</span><br><span>index 0000000..9b7d663</span><br><span>--- /dev/null</span><br><span>+++ b/doc/lchan.msc</span><br><span>@@ -0,0 +1,306 @@</span><br><span style="color: hsl(120, 100%, 40%);">+msc {</span><br><span style="color: hsl(120, 100%, 40%);">+    hscale=2;</span><br><span style="color: hsl(120, 100%, 40%);">+     bts [label="MS/BTS"], bsc[label="BSC"], bsc_ts [label="BSC timeslot FSM"],</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan[label="BSC lchan FSM"], bsc_gscon[label="BSC conn FSM"],</span><br><span style="color: hsl(120, 100%, 40%);">+        mgw_msc[label="MGW/MSC"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bts box mgw_msc [label="lchan allocation sequence"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       bts rbox mgw_msc [label="Channel Request from MS"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bts => bsc [label="RSL Channel Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc box bsc [label="lchan_select_by_type(chan_type)"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc -> bsc_lchan [label="lchan_activate(lchan, FOR_MS_CHANNEL_REQUEST)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan rbox bsc_lchan [label="Continue at\nlchan_activate()\n"];</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%);">+        bts rbox mgw_msc [label="Channel Request from BSSMAP Assignment"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon <= mgw_msc [label="BSSMAP Assignment request"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_gscon box bsc_gscon [label="lchan_select_by_chan_mode(chan_mode)"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan <- bsc_gscon [label="lchan_activate(lchan, FOR_ASSIGNMENT)"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan rbox bsc_lchan [label="Continue at\nlchan_activate()\n"];</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%);">+        bts rbox mgw_msc [label="Channel Request from Handover Decision"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc note bsc [label="target lchan typically already chosen by Handover Decision"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc -> bsc_gscon [label="GSCON_EV_HO_START (intra-BSC)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan <- bsc_gscon [label="lchan_activate(lchan, FOR_HANDOVER)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan rbox bsc_lchan [label="Continue at\nlchan_activate()\n"];</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%);">+        bts rbox mgw_msc [label="Channel Request from intra-BSC-MT-Handover"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon <- mgw_msc [label="BSSMAP Handover Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon box bsc_gscon [label="lchan_select_by_chan_mode(chan_mode)"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc box bsc [label="lchan_activate(lchan, FOR_HANDOVER)"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan rbox bsc_lchan [label="Continue at\nlchan_activate()\n"];</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%);">+  bts rbox mgw_msc [label="lchan_activate()"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan abox bsc_lchan [label="LCHAN_ST_\nWAIT_TS_READY\n(timeout: ? s, Tnnnn)"];</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%);">+  --- [label="TCH?"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan note bsc_gscon [label="This is skipped when FOR_MS_CHANNEL_REQUEST. If the MS requests</span><br><span style="color: hsl(120, 100%, 40%);">+         a TCH lchan, and we end up actually giving it a TCH because no SDCCH are available, we</span><br><span style="color: hsl(120, 100%, 40%);">+                can not set up an RTP stream because there is not even an L3 conn yet."];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan note bsc_gscon [label="The lchan FSM asks the conn FSM to have an MGW endpoint ready as</span><br><span style="color: hsl(120, 100%, 40%);">+                early as possible. Either the conn already has such MGW endpoint from a previous lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+               in which case it immediately replies, or it requests one from the MGW, in which case we</span><br><span style="color: hsl(120, 100%, 40%);">+               wait for a response in 'TCH? (2)' below."];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan -> bsc_gscon [label="GSCON_EV_ENSURE_MGW_ENDPOINT"];</span><br><span style="color: hsl(120, 100%, 40%);">+   --- [label="IF conn has user_plane.fi_bts in state ST_READY"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan <- bsc_gscon [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan box bsc_lchan [label="mgw_endpoint_available = true"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan note bsc_lchan [label="lchan_activate() continues"];</span><br><span style="color: hsl(120, 100%, 40%);">+      --- [label="ELSE (no MGW endpoint available yet)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon => mgw_msc [label="CRCX (for BTS) via mgcp_conn_create()"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon abox bsc_gscon [label="ST_WAIT_CRCX_BTS\n(timeout: ? s, Tnnnn)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan <- bsc_gscon [label="(event dispatch returns)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan note bsc_lchan [label="lchan_activate() continues"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon note bsc_gscon [label="async:"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon <= mgw_msc [label="CRCX OK (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan <- bsc_gscon [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan box bsc_lchan [label="mgw_endpoint_available = true"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan note bsc_lchan [label="As soon as we reach LCHAN_ST_WAIT_MGW_ENDPOINT_AVAILABLE, this triggers</span><br><span style="color: hsl(120, 100%, 40%);">+         immedate action (s.b.), but until then, only the flag gets set to true."];</span><br><span style="color: hsl(120, 100%, 40%);">+       ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="CRCX timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gscon note bsc_gscon [label="conn FSM should fire on CRCX timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan <- bsc_gscon [label="LCHAN_EV_MGW_ENDPOINT_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon note bsc_gscon [label="conn FSM should not assume anything and wait for</span><br><span style="color: hsl(120, 100%, 40%);">+                GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan rbox bsc_lchan [label="Do 'On any error'"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="END: 'TCH?'"];</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%);">+        bsc_lchan box bsc_lchan [label="lchan_activate() exits"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan note bsc_lchan [label="still in\nlchan_request()\nLCHAN_ST_WAIT_\nTS_READY"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_REQUESTED"];</span><br><span style="color: hsl(120, 100%, 40%);">+     ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="on error from TS or timeout:"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan rbox bsc_lchan [label="Do 'On any error'"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED"];</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%);">+  bsc_ts abox bsc_ts [label="TS_ST_IN_USE"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_READY"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan box bsc_lchan [label="lchan_fsm_\npre_lchan_activ()"];</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%);">+  bts rbox mgw_msc [label="mode FOR_MS_CHANNEL_REQUEST"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bts note bsc_lchan [label="This is the simple case where the MS requested a channel, and there is no</span><br><span style="color: hsl(120, 100%, 40%);">+             L3 conn to the MSC; no matter if this is SDDCH or a TCH channel type, we will not prepare</span><br><span style="color: hsl(120, 100%, 40%);">+             an RTP stream."];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan note bsc_lchan [label="still in lchan_fsm_\npre_lchan_activ()"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nACTIV_ACK\n(timeout: ? s, Tnnnn)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bts <= bsc_lchan [label="RSL Chan Activ (RSL_ACT_INTRA_IMM_ASS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bts note bsc_lchan [label="If any errors occur from now on, we don't want to send an RR Immediate</span><br><span style="color: hsl(120, 100%, 40%);">+            Assignment Reject anymore."];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan box bsc_lchan [label="sent_chan_activ = true"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="on timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan rbox bsc_lchan [label="Continue at: 'On any error', 'unrecoverable'"];</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%);">+  bts => bsc_lchan [label="RSL Chan Activ ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRLL_ESTABLISH\nT3101"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan note bsc_lchan [label="Now the lchan is assigned, but has no L3 conn yet. On errors,</span><br><span style="color: hsl(120, 100%, 40%);">+           this will either go into graceful release or into broken state, but will not trigger any</span><br><span style="color: hsl(120, 100%, 40%);">+              events to a (non-existing) conn."];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="on timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts <= bsc_lchan [label="RSL RF Channel Release"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_RF_RELEASE_ACK\n(T?, 4s)"];</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%);">+  bts => bsc_lchan [label="RLL Establish Ind"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];</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%);">+  bts rbox mgw_msc [label="modes FOR_ASSIGNMENT and FOR_HANDOVER"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan note bsc_lchan [label="still in lchan_fsm_\npre_lchan_activ()"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nACTIV_ACK\n(timeout: ? s, Tnnnn)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bts <= bsc_lchan [label="RSL Chan Activ (RSL_ACT_INTRA_NORM_ASS)",ID=FOR_ASSIGNMENT];</span><br><span style="color: hsl(120, 100%, 40%);">+    bts <= bsc_lchan [label="RSL Chan Activ (RSL_ACT_INTER_ASYNC)",ID=FOR_HANDOVER];</span><br><span style="color: hsl(120, 100%, 40%);">+ ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="on timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan rbox bsc_lchan [label="Continue at: 'On any error', 'unrecoverable'"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ---;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts => bsc_lchan [label="RSL Chan Activ ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRLL_ESTABLISH\nT3101"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="on timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan -> bsc_lchan [label="lchan_fsm_pre_rf_release()"];</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%);">+  bts => bsc_lchan [label="RLL Establish Indication"];</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%);">+        --- [label="TCH? (2)"];</span><br><span style="color: hsl(120, 100%, 40%);">+     --- [label="mgw_endpoint_available == false?"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nMGW_ENDPOINT_\nAVAILABLE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan note bsc_lchan [label="rely on conn FSM timeout; apply only a long sanity timeout."];</span><br><span style="color: hsl(120, 100%, 40%);">+     ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_gscon <= mgw_msc [label="CRCX OK (for BTS)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan <- bsc_gscon [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan box bsc_lchan [label="mgw_endpoint_available = true"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan <- bsc_lchan [label="re-invoke lchan_fsm_pre_lchan_activ()"];</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="END: 'TCH? (2)'"];</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%);">+        --- [label="is BTS using IPA Abis? (osmo-bts, ip.access)"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nIPACC_CRCX_ACK\n(timeout: ? s, Tnnnn)"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts <= bsc_lchan [label="IPACC CRCX"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="on timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan -> bsc_lchan [label="lchan_graceful_release()"];</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%);">+  bts => bsc_lchan [label="IPACC CRCX ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bts note bsc_lchan [label="The IPACC CRCX ACK tells us what port the IPA Abis based BTS has</span><br><span style="color: hsl(120, 100%, 40%);">+              assigned to this lchan. AoIP: we need to forward this to the MGW (BTS side) with an MDCX;</span><br><span style="color: hsl(120, 100%, 40%);">+             SCCPlite: we forward this to the MSC during BSSMAP Assignment Complete (TODO: is this</span><br><span style="color: hsl(120, 100%, 40%);">+         correct??)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nIPACC_MDCX_ACK\n(timeout: ? s, Tnnnn)"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts <= bsc_lchan [label="IPACC MDCX"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts note bsc_lchan [label="The IPACC MDCX tells IPA Abis based BTSes the IP address and RTP port</span><br><span style="color: hsl(120, 100%, 40%);">+         assigned by the BTS side of the MGW. AoIP: the MGW CRCX (BTS) must thus happen before</span><br><span style="color: hsl(120, 100%, 40%);">+         this; SCCPlite: the RTP port is already known from the timeslot+multiplex information."];</span><br><span style="color: hsl(120, 100%, 40%);">+        ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="on timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan -> bsc_lchan [label="lchan_graceful_release()"];</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%);">+  bts => bsc_lchan [label="IPACC MDCX ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="END: is BTS using IPA Abis? (osmo-bts, ip.access)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    |||;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan box bsc_lchan [label="lchan_fsm_post_lchan_activ()"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bts <= bsc_gscon [label="RR Assignment",ID="BSSMAP Assignment Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bts <= bsc_gscon [label="RR Handover Command",ID="intra-BSC HO"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_gscon => mgw_msc [label="BSSMAP Handover\nRequest Acknowledge",ID="inter-BSC-MT HO"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  ---[label="On error"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan rbox bsc_lchan [label="Continue at 'When the lchan is no longer used'"];</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%);">+        bts => bsc_gscon [label="RR Assignment Complete",ID="BSSMAP Assignment Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bts => bsc_gscon [label="RR Handover Detect",ID="intra-BSC HO"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bts => bsc_gscon [label="RR Handover Accept",ID="inter-BSC-MT HO"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon note bsc_gscon [label="conn FSM takes care of MGW endpoints for BTS side (possibly</span><br><span style="color: hsl(120, 100%, 40%);">+             redirect) and MSC side (possibly create). More information in e.g. assignment.msc and</span><br><span style="color: hsl(120, 100%, 40%);">+         handover.msc"];</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%);">+        bts rbox mgw_msc [label="When the lchan is no longer used"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="IF the MS or BTS release the lchan"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts -> bsc_lchan [label="RLL Release Ind for SAPI=0"];</span><br><span style="color: hsl(120, 100%, 40%);">+   --- [label="IF the BSC other than the conn FSM decides to release"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc -> bsc_lchan [label="LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+     --- [label="IF the MSC or conn FSM release the lchan"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan <- bsc_gscon [label="LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+       ---;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc note bsc_gscon [label="The LCHAN_EV_RELEASE's data pointer possibly indicates an error</span><br><span style="color: hsl(120, 100%, 40%);">+           cause"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan note bsc_gscon [label="If the conn FSM requested a release, it probably has already</span><br><span style="color: hsl(120, 100%, 40%);">+    forgotten about this lchan. However, if the MS/BTS initiated the release, make sure the conn FSM</span><br><span style="color: hsl(120, 100%, 40%);">+      is informed:"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan box bsc_lchan [label="lchan_graceful_release()"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nSAPIS_RELEASED\nT3109"];</span><br><span style="color: hsl(120, 100%, 40%);">+   --- [label="TCH and got as far as Chan Activ Ack?"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bts <= bsc_lchan [label="RSL Deactivate SACCH"];</span><br><span style="color: hsl(120, 100%, 40%);">+ ---;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts <= bsc_lchan [label="RLL Release Request (Local End)..."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts <= bsc_lchan [label="...for all SAPIs except [0]"];</span><br><span style="color: hsl(120, 100%, 40%);">+  |||;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="SAPI[0] in use?"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan note bsc_lchan [label="for bts->nokia.no_loc_rel_cnf we do not expect Release Confirm</span><br><span style="color: hsl(120, 100%, 40%);">+               messages and this state immediately advances to lchan_fsm_pre_rf_release()"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="on timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan box bsc_lchan [label="Anyway try RF Channel Release, continue</span><br><span style="color: hsl(120, 100%, 40%);">+          with lchan_fsm_wait_before_rf_release()"];</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%);">+  bts => bsc_lchan [label="RLL Release Confirm..."];</span><br><span style="color: hsl(120, 100%, 40%);">+       bts => bsc_lchan [label="...for each SAPI except [0]"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan box bsc_lchan [label="Stay in\nLCHAN_ST_WAIT_\nSAPIS_RELEASED\nuntil only SAPI[0] remains active"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="END: 'SAPI[0] in use?'"];</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%);">+        bsc_lchan box bsc_lchan [label="lchan_fsm_wait_before_rf_release()"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nBEFORE_RF_RELEASE\nT3111"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan -> bsc_gscon [label="GSCON_EV_FORGET_LCHAN (data=lchan)"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon note bsc_gscon [label="conn FSM immediately forgets about the lchan"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_gscon => mgw_msc [label="BSSMAP Clear Request?"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan box bsc_lchan [label="T3111 expires"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan box bsc_lchan [label="lchan_fsm_pre_rf_release()"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRF_RELEASE_ACK\nT3111"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan box bsc_lchan [label="for each bsc_rll_req matching this lchan: disable timer, call</span><br><span style="color: hsl(120, 100%, 40%);">+            cb(BSC_RLLR_IND_REL_IND)"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bts <= bsc_lchan [label="RSL RF Channel Release"];</span><br><span style="color: hsl(120, 100%, 40%);">+       ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="on timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan rbox bsc_lchan [label="Continue at: 'On any error', 'unrecoverable'"];</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%);">+  bts => bsc_lchan [label="RSL RF Channel Release Ack"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan box bsc_lchan [label="lchan_fsm_post_rf_release()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      |||;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="IF an error cause was indicated on LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nAFTER_ERROR\n(timeout: T3111+2 s, T?)"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan box bsc_lchan [label="timer expires"];</span><br><span style="color: hsl(120, 100%, 40%);">+    --- [label="END: 'an error cause was indicated on LCHAN_EV_RELEASE'"];</span><br><span style="color: hsl(120, 100%, 40%);">+      |||;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan box bsc_lchan [label="lchan_fsm_release_complete()"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts abox bsc_ts [label="TS_ST_UNUSED"];</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%);">+        bts rbox mgw_msc [label="On any error"];</span><br><span style="color: hsl(120, 100%, 40%);">+    |||;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="IF FOR_MS_CHANNEL_REQUEST && !sent_chan_activ"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bts <= bsc_lchan [label="RR Immediate Assign Reject"];</span><br><span style="color: hsl(120, 100%, 40%);">+   |||;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="IF FOR_ASSIGNMENT or FOR_HANDOVER"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon note bsc_gscon [label="conn FSM shall immediately 'forget' the lchan"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gscon => mgw_msc [label="BSSMAP\nAssignment Failure",ID=FOR_ASSIGNMENT];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_gscon => mgw_msc [label="BSSMAP\nHandover Failure",ID="inter-BSC-MT HO"];</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%);">+  --- [label="IF unrecoverable error"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan abox bsc_lchan [label="LCHAN_ST_BORKEN"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan note bsc_lchan [label="The broken state usually stays around</span><br><span style="color: hsl(120, 100%, 40%);">+           until the BTS disconnects."];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts note bsc_lchan [label="If an ACK comes in late, for specific BTS models, we may choose to</span><br><span style="color: hsl(120, 100%, 40%);">+            'repair' the lchan so that it is usable again."];</span><br><span style="color: hsl(120, 100%, 40%);">+        bts -> bsc_lchan [label="Chan Release ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan -> bsc_lchan [label="lchan_fsm_post_rf_release()"];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/doc/ms-channel-request.msc b/doc/ms-channel-request.msc</span><br><span>index c0ef60f..1c5b4bf 100644</span><br><span>--- a/doc/ms-channel-request.msc</span><br><span>+++ b/doc/ms-channel-request.msc</span><br><span>@@ -1,8 +1,8 @@</span><br><span> msc {</span><br><span style="color: hsl(0, 100%, 40%);">-   hscale=3;</span><br><span style="color: hsl(0, 100%, 40%);">-       ms [label="MS"], bts [label="BTS"], bsc[label="BSC"], bsc_gscon[label="BSC conn FSM"];</span><br><span style="color: hsl(120, 100%, 40%);">+        hscale=2;</span><br><span style="color: hsl(120, 100%, 40%);">+     ms [label="MS"], bts [label="BTS"], bsc[label="BSC"], bsc_lchan[label="BSC lchan FSM"];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     ms note bsc_gscon [label="lchan allocation sequence for RSL Channel Request"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ms note bsc_lchan [label="lchan allocation sequence for RSL Channel Request"];</span><br><span> </span><br><span>         ms => bts [label="RR Channel Request"];</span><br><span>         bts => bsc [label="RSL Channel Request"];</span><br><span>@@ -13,51 +13,47 @@</span><br><span>                 longer concerned (rsl_rx_pchan_rqd())."];</span><br><span>       bsc note bsc [label="Always try to allocate an SDCCH regardless of the requested type, only if no</span><br><span>               SDCCH is available, look for the actually requested channel type."];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="lchan_alloc(SDCCH, allow_bigger=0)"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc box bsc [label="lchan_select_by_type(SDCCH)"];</span><br><span> </span><br><span>     --- [label="IF no lchan is available (neither SDCCH nor requested type)"];</span><br><span>         bsc note bsc [label="Figure out T3122 value from bts->T3122, network->T3122 or</span><br><span>            GSM_T3122_DEFAULT"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="rsl_send_imm_ass_rej()"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc box bsc [label="rsl_send_imm_ass_rej(wait_ind=T3122)"];</span><br><span>        bsc note bsc [label="..."];</span><br><span>        bts <= bsc [label="RR Immediate Assign Reject"];</span><br><span>        ms <= bts [label="RR Immediate Assign Reject (possibly grouped with up to 4 others)"];</span><br><span>  bsc note bsc [label="rsl_rx_pchan_rqd() exits, no channel is allocated."];</span><br><span style="color: hsl(0, 100%, 40%);">-    ---;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="END: no lchan is available"];</span><br><span> </span><br><span>      bsc box bsc [label="Store RACH data in lchan->rqd_ref, rqd_ta"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc abox bsc [label="Start lchan->act_timer (4s, lchan_act_tmr_cb())"];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="rsl_chan_activate_lchan(RSL_ACT_INTRA_IMM_ASS)"];</span><br><span style="color: hsl(0, 100%, 40%);">- --- [label="is the chosen lchan on dynamic timeslot that is currently used as PDCH?"];</span><br><span style="color: hsl(0, 100%, 40%);">-        bsc box bsc [linecolor=red,label="Osmocom style dyn TS use the lchan->act_timer for an RSL RF</span><br><span style="color: hsl(0, 100%, 40%);">-           Channel Release, to release PDCH mode. This will actually overwrite above act_timer!"];</span><br><span style="color: hsl(0, 100%, 40%);">-    bts <= bsc [label="i) RSL RF Chan Release of PDCH (Osmocom dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bts <= bsc [label="OR ii) RSL PDCH Deact (ip.access dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc -> bsc_gscon [label="gsm0808_assign_req() returns early"];</span><br><span style="color: hsl(0, 100%, 40%);">-     bsc_gscon abox bsc_gscon [label="ST_WAIT_ASS_COMPL (GSM0808_T10_VALUE=6s)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc -> bsc_lchan [label="lchan_allocate(FOR_MS_CHANNEL_REQUEST)"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_ACTIV_ACK\nT3103"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan note bsc_lchan [label="The lchan FSM knows that FOR_MS_CHANNEL_REQUEST is about</span><br><span style="color: hsl(120, 100%, 40%);">+                Immediate Assignment."];</span><br><span style="color: hsl(120, 100%, 40%);">+ bts <= bsc_lchan [label="RSL Chan Activ (Immediate Assignment)"];</span><br><span>       ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts note bsc_gscon [linecolor="red",</span><br><span style="color: hsl(0, 100%, 40%);">-          label="Osmocom style dyn TS use lchan->act_timer to watch over RF Chan Release, but there</span><br><span style="color: hsl(0, 100%, 40%);">-               seems to be no timer watching over PDCH Deact!"];</span><br><span style="color: hsl(0, 100%, 40%);">-  ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="i) RSL RF Chan Release ACK (Osmocom dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bts => bsc [label="OR ii) RSL PDCH Deact ACK (ip.access dyn TS)"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc box bsc [label="rsl_chan_activate_lchan() re-invoked"];</span><br><span style="color: hsl(120, 100%, 40%);">+ --- [label="on any error"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bts <= bsc_lchan [label="RR Immediate Assign Reject"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ms <= bts [label="RR Immediate Assign Reject (possibly grouped with up to 4 others)"];</span><br><span>  ---;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc box bsc [label="lchan->state = LCHAN_S_ACT_REQ"];</span><br><span style="color: hsl(0, 100%, 40%);">-      bts <= bsc [label="RSL Chan Activ: Immediate Assignment"];</span><br><span>      ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bsc note bsc [label="Timeout of lchan->act_timer causes the</span><br><span style="color: hsl(0, 100%, 40%);">-             lchan->state to go to LCHAN_S_BROKEN, but no events or actions</span><br><span style="color: hsl(0, 100%, 40%);">-               are triggered."];</span><br><span style="color: hsl(120, 100%, 40%);">+        bts => bsc_lchan [label="RSL Chan Activ ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRLL_ESTABLISH\ncontinue T3103"];</span><br><span>  ...;</span><br><span style="color: hsl(0, 100%, 40%);">-    bts => bsc [label="RSL Chan Activ ACK"];</span><br><span style="color: hsl(0, 100%, 40%);">-   bsc box bsc [label="rsl_rx_chan_act_ack()"];</span><br><span style="color: hsl(0, 100%, 40%);">-  bsc box bsc [label="Stop lchan->act_timer"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc box bsc [label="lchan->state = LCHAN_S_ACTIVE"];</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc -> bsc [label="S_LCHAN_ACTIVATE_ACK (has no effect)"];</span><br><span style="color: hsl(0, 100%, 40%);">- bsc note bsc [label="Since this was an Immediate Assignment, no further action is required on</span><br><span style="color: hsl(0, 100%, 40%);">-              behalf of the BSC. The MS is now free to use the lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="on timeout"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan box bsc_lchan [label="lchan_error_release(deact_sacch=true)"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_RF_RELEASE_ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bts <= bsc_lchan [label="RLL Release Request (Local End)..."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts <= bsc_lchan [label="...for all SAPIs including [0]"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bts <= bsc_lchan [label="RSL Deactivate SACCH"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bts <= bsc_lchan [label="RSL RF Channel Release"];</span><br><span style="color: hsl(120, 100%, 40%);">+       ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts => bsc_lchan [label="RSL RF Channel Release ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_AFTER_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+       ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+ ---;</span><br><span style="color: hsl(120, 100%, 40%);">+  ms => bsc_lchan [label="RLL Establish Ind"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan box bsc_lchan [label="associate lchan FSM with new conn FSM"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];</span><br><span> }</span><br><span>diff --git a/doc/timeslot-fsm.dot b/doc/timeslot-fsm.dot</span><br><span>new file mode 100644</span><br><span>index 0000000..79e56c9</span><br><span>--- /dev/null</span><br><span>+++ b/doc/timeslot-fsm.dot</span><br><span>@@ -0,0 +1,36 @@</span><br><span style="color: hsl(120, 100%, 40%);">+digraph G {</span><br><span style="color: hsl(120, 100%, 40%);">+rankdir=TB;</span><br><span style="color: hsl(120, 100%, 40%);">+       </span><br><span style="color: hsl(120, 100%, 40%);">+      invisible [style="invisible"]</span><br><span style="color: hsl(120, 100%, 40%);">+       invisible2 [style="invisible"]</span><br><span style="color: hsl(120, 100%, 40%);">+      NOT_INITIALIZED</span><br><span style="color: hsl(120, 100%, 40%);">+       lchan [label="lchan FSM",shape=box3d];</span><br><span style="color: hsl(120, 100%, 40%);">+      UNUSED</span><br><span style="color: hsl(120, 100%, 40%);">+        IN_USE</span><br><span style="color: hsl(120, 100%, 40%);">+        BORKEN</span><br><span style="color: hsl(120, 100%, 40%);">+        PDCH</span><br><span style="color: hsl(120, 100%, 40%);">+  WAIT_PDCH_ACT</span><br><span style="color: hsl(120, 100%, 40%);">+ WAIT_PDCH_DEACT</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     invisible -> NOT_INITIALIZED [label="OML\nOpstart ACK",style=dotted]</span><br><span style="color: hsl(120, 100%, 40%);">+     invisible2 -> NOT_INITIALIZED [label="RSL\nbootstrapped",style=dotted]</span><br><span style="color: hsl(120, 100%, 40%);">+   </span><br><span style="color: hsl(120, 100%, 40%);">+      NOT_INITIALIZED -> UNUSED [label="OML+RSL ready"]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      UNUSED -> IN_USE [label="first\nlchan\nrequested\nby lchan\nFSM"]</span><br><span style="color: hsl(120, 100%, 40%);">+        IN_USE -> UNUSED [label="last lchan\nunused"]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  UNUSED -> PDCH [label="onenter:\ndedicated PDCH\nand GPRS\nis enabled"]</span><br><span style="color: hsl(120, 100%, 40%);">+  UNUSED -> WAIT_PDCH_ACT [label="onenter:\ndyn TS\nand GPRS\nis enabled"]</span><br><span style="color: hsl(120, 100%, 40%);">+ WAIT_PDCH_ACT -> PDCH [label="dyn TS:\nPDCH activated"]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        PDCH -> WAIT_PDCH_DEACT [label="dyn TS:\nlchan of specific\npchan requested"]</span><br><span style="color: hsl(120, 100%, 40%);">+    WAIT_PDCH_DEACT -> UNUSED [label="lchan\nunused\n(e.g. error)",style=dashed]</span><br><span style="color: hsl(120, 100%, 40%);">+     WAIT_PDCH_DEACT -> IN_USE [label="dyn TS:\nPDCH released"]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     lchan -> {UNUSED} [label="TS_EV_LCHAN_\nREQUESTED",style=dotted]</span><br><span style="color: hsl(120, 100%, 40%);">+ {IN_USE} -> lchan [label="LCHAN_EV_\nTS_READY",style=dotted]</span><br><span style="color: hsl(120, 100%, 40%);">+     lchan -> IN_USE [label="TS_EV_LCHAN_\nUNUSED",style=dotted]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    {WAIT_PDCH_ACT,WAIT_PDCH_DEACT} -> BORKEN [label=timeout,style=dashed]</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/doc/timeslot.msc b/doc/timeslot.msc</span><br><span>new file mode 100644</span><br><span>index 0000000..9a8c360</span><br><span>--- /dev/null</span><br><span>+++ b/doc/timeslot.msc</span><br><span>@@ -0,0 +1,98 @@</span><br><span style="color: hsl(120, 100%, 40%);">+msc {</span><br><span style="color: hsl(120, 100%, 40%);">+    hscale=2;</span><br><span style="color: hsl(120, 100%, 40%);">+     bts [label="MS/BTS"], bsc[label="BSC"], bsc_ts[label="BSC timeslot FSM"], bsc_lchan[label="BSC lchan FSM"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts abox bsc_ts [label="NOT_INITIALIZED (no timeout)"];</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%);">+  bsc note bsc_ts [label="OML and RSL may be established in any order"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bts => bsc_ts [label="OML: Channel OPSTART ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc -> bsc_ts [label="RSL bootstrapped"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts abox bsc_ts [label="UNUSED (no timeout)"];</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%);">+  bts rbox bsc_lchan [label="UNUSED, onenter"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_ts abox bsc_ts [label="UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="GPRS enabled?"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="IF: dedicated PDCH?"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts abox bsc_ts [label="PDCH (no timeout)"];</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%);">+  --- [label="IF: dynamic timeslot"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts abox bsc_ts [label="WAIT_PDCH_ACT (?s, Tnnnn)"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bts <= bsc_ts [label="RSL Chan Activ of PDCH",ID="Osmocom style"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bts <= bsc_ts [label="RSL PDCH Act",ID="ip.access style"];</span><br><span style="color: hsl(120, 100%, 40%);">+     ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="timeout:"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts abox bsc_ts [label="BORKEN"];</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%);">+  bts => bsc_ts [label="RSL RF Chan Activ ACK",ID="Osmocom style"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bts => bsc_ts [label="RSL PDCH Act ACK",ID="ip.access style"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts abox bsc_ts [label="PDCH (no timeout)"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   --- [label="END: GPRS enabled?"];</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%);">+        bts rbox bsc_lchan [label="UNUSED, on event"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_ts abox bsc_ts [label="UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_REQUESTED (data=lchan)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts abox bsc_ts [label="IN_USE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_READY"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bts <= bsc_lchan [label="RSL Chan Activ (and so on)"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts rbox bsc_lchan [label="IN_USE, second lchan"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_REQUESTED (data=lchan)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_READY"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bts <= bsc_lchan [label="RSL Chan Activ (and so on)"];</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%);">+  bts rbox bsc_lchan [label="IN_USE, when lchan FSM releases (both regularly, or due to error)"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED (data=lchan)"];</span><br><span style="color: hsl(120, 100%, 40%);">+   --- [label="IF all lchan->fi->state == LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts abox bsc_ts [label="UNUSED"];</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%);">+      bts rbox bsc_lchan [label="PDCH on lchan request"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts note bsc_lchan [label="TS_EV_LCHAN_REQUESTED should only come in on</span><br><span style="color: hsl(120, 100%, 40%);">+               lchans where it makes sense, both from TS kind as well as not</span><br><span style="color: hsl(120, 100%, 40%);">+         conflicting with other users of the lchan."];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_REQUESTED"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts abox bsc_ts [label="WAIT_PDCH_DEACT (?s, Tnnnn)"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bts <= bsc_ts [label="RSL RF Chan Release of PDCH",ID="Osmocom style"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bts <= bsc_ts [label="RSL PDCH Deact",ID="ip.access style"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="timeout:"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts abox bsc_ts [label="BORKEN"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_ERROR"];</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%);">+  bts => bsc_ts [label="RSL RF Chan Release ACK",ID="Osmocom style"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bts => bsc_ts [label="RSL PDCH Deact ACK",ID="ip.access style"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="IF all lchan->fi->state == LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts note bsc_lchan [label="If the lchan FSM decided to give up in the</span><br><span style="color: hsl(120, 100%, 40%);">+         meantime, nr of active lchans might have dropped back to zero."];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts abox bsc_ts [label="UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts note bsc_ts [label="onenter at UNUSED state will trigger back to</span><br><span style="color: hsl(120, 100%, 40%);">+          PDCH mode"];</span><br><span style="color: hsl(120, 100%, 40%);">+     |||;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="IF at least one lchan->state != LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_ts abox bsc_ts [label="IN_USE"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts rbox bsc_ts [label="Continue at 'IN_USE' above"];</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%);">+        bts rbox bsc_lchan [label="on erratic event"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_ERROR"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan box bsc_lchan [label="release lchan"];</span><br><span style="color: hsl(120, 100%, 40%);">+    ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts note bsc_ts [label="log error but ignore"];</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>diff --git a/doc/ts-and-lchan-fsm-lifecycle.msc b/doc/ts-and-lchan-fsm-lifecycle.msc</span><br><span>new file mode 100644</span><br><span>index 0000000..79d32c5</span><br><span>--- /dev/null</span><br><span>+++ b/doc/ts-and-lchan-fsm-lifecycle.msc</span><br><span>@@ -0,0 +1,116 @@</span><br><span style="color: hsl(120, 100%, 40%);">+msc {</span><br><span style="color: hsl(120, 100%, 40%);">+        hscale=2;</span><br><span style="color: hsl(120, 100%, 40%);">+     bts [label="MS/BTS"], bsc[label="BSC"], bsc_ts[label="BSC timeslot FSM"], bsc_lchan[label="BSC lchan FSM"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc box bsc [label="gsm_bts_alloc()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc box bsc [label="bts->c0 = gsm_bts_trx_alloc()"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc -> bsc_ts;</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts box bsc_ts [label="trx->ts[*].fi = osmo_fsm_inst_alloc(timeslot_fsm)"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_ts abox bsc_ts [label="TS_ST_NOT_INITIALIZED"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc -> bsc_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_lchan box bsc_lchan [label="ts->lchan[*].ts = ts;\nts->lchan[*].nr = i;"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan box bsc_lchan [label="ts->lchan[*].fi = NULL"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts note bsc_lchan [label="lchan_select() will only pick lchans from initialized timeslots of</span><br><span style="color: hsl(120, 100%, 40%);">+         the right pchan kind. lchan_select() shall OSMO_ASSERT(lchan->fi)."];</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%);">+        bts rbox bsc_lchan [label="reading config file"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc box bsc [label="timeslot N"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc box bsc [label="phys_chan_config X"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_ts box bsc_ts [label="ts->pchan_from_config = X"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_ts note bsc_ts [label="still TS_ST_NOT_INITIALIZED"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc box bsc [label="trx 1..*"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc box bsc [label="bts->trx_list add gsm_bts_trx_alloc()"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts rbox bsc_lchan [label="same as for c0 above"];</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%);">+  bts rbox bsc_lchan [label="Starting Operation"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bts => bsc_ts [label="OML Channel OPSTART ACK"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts box bsc_ts [label="ts_on_oml_opstart()"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_ts box bsc_ts [label="ts->pchan_on_init = pchan_from_config"];</span><br><span style="color: hsl(120, 100%, 40%);">+       --- [label="IF dedicated TS"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_ts box bsc_ts [label="ts->pchan = ts->pchan_on_init"];</span><br><span style="color: hsl(120, 100%, 40%);">+    --- [label="ELSE: dyn TS"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts box bsc_ts [label="ts->pchan = NONE"];</span><br><span style="color: hsl(120, 100%, 40%);">+    --- [label="END: dyn TS"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts note bsc_lchan [label="Normally, the lchan FSM never terminates. Logic dictates that</span><br><span style="color: hsl(120, 100%, 40%);">+              the lchan is a child of the timeslot FSM, but it's not actually of functional importance</span><br><span style="color: hsl(120, 100%, 40%);">+          beyond basic sanity. Parent term event: TS_EV_LCHAN_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc_ts box bsc_ts [label="Determine N = maximum number of lchans applicable to pchan_on_init"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts -> bsc_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan box bsc_lchan [label="ts->lchan[all N].type = osmo_fsm_inst_alloc(lchan_fsm)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED\n(initial state)"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts -> bsc_ts [label="ts_check_init()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc -> bsc_ts [label="RSL bootstrapped"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts -> bsc_ts [label="ts_check_init()"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts box bsc_ts [label="ts_check_init()"];</span><br><span style="color: hsl(120, 100%, 40%);">+        --- [label="as soon as both OML and RSL are ready:"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_ts box bsc_ts [label="ts_on_init()"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_ts abox bsc_ts [label="TS_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="dyn TS"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_ts box bsc_ts [label="onenter of TS_ST_UNUSED:"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_ts abox bsc_ts [label="TS_ST_WAIT_PDCH_ACT"];</span><br><span style="color: hsl(120, 100%, 40%);">+   ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts abox bsc_ts [label="PDCH"];</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="END: dyn TS"];</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="END: OML and RSL ready"];</span><br><span style="color: hsl(120, 100%, 40%);">+       ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc box bsc [label="lchan_select() picks an unused lchan"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc -> bsc_lchan [label="lchan_allocate()"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan -> bsc_ts [label="TS_EV_LCHAN_REQUESTED"];</span><br><span style="color: hsl(120, 100%, 40%);">+     </span><br><span style="color: hsl(120, 100%, 40%);">+      --- [label="dyn TS"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_ts note bsc_ts [label="possibly switch from PDCH...\n(see timeslot FSM)"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_ts box bsc_ts [label="ts->pchan =\n requested GSM_PCHAN_XXX type"];</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%);">+        bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_READY"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan note bsc_lchan [label="RSL Chan Alloc and so fort..."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];</span><br><span style="color: hsl(120, 100%, 40%);">+ ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc -> bsc_lchan [label="LCHAN_EV_RELEASE"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_lchan note bsc_lchan [label="...RSL RF Chan Release..."];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts abox bsc_ts [label="TS_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="dyn TS"];</span><br><span style="color: hsl(120, 100%, 40%);">+       bsc_ts note bsc_ts [label="possibly switch to PDCH"];</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%);">+  bts rbox bsc_lchan [label="BTS RSL is dropped"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc box bsc [label="ipaccess_drop_rsl()"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc -> bsc_ts [label="ts[*]:"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts abox bsc_ts [label="TS_ST_NOT_INITIALIZED"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts note bsc_lchan [label="If it's just the RSL being dropped, transition lchan FSMs to</span><br><span style="color: hsl(120, 100%, 40%);">+           LCHAN_ST_UNUSED, but keep them allocated. Unless OML is re-established, any vty pchan</span><br><span style="color: hsl(120, 100%, 40%);">+         modifications must not take effect."];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_ts -> bsc_lchan [label="lchan[*]:"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED (ignored)"];</span><br><span style="color: hsl(120, 100%, 40%);">+      ...;</span><br><span style="color: hsl(120, 100%, 40%);">+  --- [label="when RSL comes back later:"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc -> bsc_ts [label="RSL bootstrapped"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts box bsc_ts [label="ts_check_init()"];</span><br><span style="color: hsl(120, 100%, 40%);">+        bsc_ts rbox bsc_ts [label="see ts_check_init() above"];</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%);">+  bts rbox bsc_lchan [label="BTS OML is dropped"];</span><br><span style="color: hsl(120, 100%, 40%);">+    bsc note bsc [label="As part of OML drop, RSL is also dropped:"];</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc box bsc [label="ipaccess_drop_rsl()"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc -> bsc_ts [label="ts[*]:"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts abox bsc_ts [label="TS_ST_NOT_INITIALIZED"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc rbox bsc [label="see 'BTS RSL is dropped' above"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc -> bsc_ts [label="ts[*]:"];</span><br><span style="color: hsl(120, 100%, 40%);">+  bsc_ts -> bsc_lchan [label="lchan[*]:"];</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_lchan box bsc_lchan [label="osmo_fsm_inst_term()"];</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED (ignored)"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc_lchan box bsc_lchan [label="lchan->fi = NULL"];</span><br><span style="color: hsl(120, 100%, 40%);">+      bsc rbox bsc [label="Continue at 'Starting Operation'"];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/9489">change 9489</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/9489"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I18d60de5ee932c962aad0a532965a55d570bb936 </div>
<div style="display:none"> Gerrit-Change-Number: 9489 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>