doc: update/fix FSM charts

These reflect the plan for refactoring, and will be implemented by
I82e3f918295daa83274a4cf803f046979f284366 and
Id7a4407d9b63be05ce63f5f2768b7d7e3d5c86fb

Change-Id: I29e31b753e23a4207662e0e385a337e7df836f45
This commit is contained in:
Neels Hofmeyr 2018-06-16 16:08:55 +02:00
parent 431e085736
commit 3b5de1b668
23 changed files with 833 additions and 865 deletions

View File

@ -3,20 +3,27 @@ SUBDIRS = \
$(NULL)
msc: \
$(builddir)/legend_for_ladder_diagrams.png \
$(builddir)/handover.png \
$(builddir)/assignment.png \
$(builddir)/lchan-release.png \
$(builddir)/ms-channel-request.png \
$(builddir)/timeslot.png \
$(builddir)/lchan.png \
$(builddir)/ts-and-lchan-fsm-lifecycle.png \
$(builddir)/handover-inter-bsc-mo.png \
$(builddir)/handover-inter-bsc-mt.png \
$(builddir)/handover-inter-bsc-out.png \
$(builddir)/handover-inter-bsc-in.png \
$(builddir)/mgw-endpoint.png \
$(NULL)
dot: \
$(builddir)/legend_for_fsm_diagrams.png \
$(builddir)/assignment-fsm.png \
$(builddir)/timeslot-fsm.png \
$(builddir)/lchan-fsm.png \
$(builddir)/lchan-rtp-fsm.png \
$(builddir)/mgw-endpoint-fsm.png \
$(builddir)/handover-intra-bsc-fsm.png \
$(builddir)/handover-inter-bsc-out-fsm.png \
$(builddir)/handover-inter-bsc-in-fsm.png \
$(NULL)
$(builddir)/%.png: $(srcdir)/%.msc

42
doc/assignment-fsm.dot Normal file
View File

@ -0,0 +1,42 @@
digraph G {
rankdir=TB
labelloc=t; label="Assignment FSM"
WAIT_LCHAN_ACTIVE
WAIT_RR_ASS_COMPLETE
WAIT_LCHAN_ESTABLISHED
WAIT_MGW_ENDPOINT_TO_MSC
terminate [shape=octagon]
gscon [label="conn FSM",shape=box3d]
gscon2 [label="conn FSM",shape=box3d]
lchan [label="lchan FSM\n(new lchan)",shape=box3d]
old_lchan [label="old lchan",shape=box3d]
bssap [label="osmo_bsc_bssap.c",shape=box]
invisible [style="invisible"]
invisible -> bssap [label="BSSMAP Assignment Request",style=dotted]
invisible -> old_lchan [style=invisible,arrowhead=none]
bssap -> gscon [label="GSCON_EV_ASSIGNMENT_START\ndata=struct assignment_request",style=dotted]
gscon -> WAIT_LCHAN_ACTIVE [label="assignment_fsm_start()",style=dotted]
WAIT_LCHAN_ACTIVE -> lchan [label="lchan_activate()\nFOR_ASSIGNMENT",style=dotted]
lchan -> WAIT_LCHAN_ACTIVE [label="ASSIGNMENT_EV_\nLCHAN_\nACTIVE,ERROR",style=dotted]
lchan -> WAIT_LCHAN_ESTABLISHED [label="ASSIGNMENT_EV_\nLCHAN_\nESTABLISHED,ERROR",style=dotted]
WAIT_LCHAN_ACTIVE -> WAIT_RR_ASS_COMPLETE
WAIT_RR_ASS_COMPLETE -> old_lchan [label="RR Assignment\nCommand",style=dotted,constraint=false]
lchan -> WAIT_RR_ASS_COMPLETE [label="RR Assignment\nComplete",style=dotted]
WAIT_RR_ASS_COMPLETE -> WAIT_LCHAN_ESTABLISHED
WAIT_LCHAN_ESTABLISHED -> WAIT_MGW_ENDPOINT_TO_MSC [label="TCH"]
WAIT_LCHAN_ESTABLISHED -> terminate [label="non-TCH"]
WAIT_MGW_ENDPOINT_TO_MSC -> terminate
WAIT_MGW_ENDPOINT_TO_MSC -> gscon2 [label="gscon_connect_\nmgw_to_msc()",style=dotted]
gscon2 -> WAIT_MGW_ENDPOINT_TO_MSC [label="ASSIGNMENT_EV_\nMSC_MGW_OK",style=dotted]
terminate -> gscon2 [label="GSCON_EV_\nASSIGNMENT_END",style=dotted]
}

View File

@ -1,126 +1,72 @@
msc {
hscale=3;
ms [label="MS/BTS"], bsc_lchan[label="BSC lchan FSM"],
bsc_gscon[label="BSC conn FSM"], bsc_mgcp[label="BSC mgcp FSM"], mgw_msc[label="MGW/MSC"];
hscale=2;
ms [label="MS/BTS"], lchan[label="BSC lchan FSM"], ass[label="BSC Assignment FSM"],
gscon[label="BSC conn FSM"], msc_[label="MSC"];
ms note mgw_msc [label="lchan allocation sequence for BSSMAP Assignment Request"];
ms note msc_ [label="lchan allocation sequence for BSSMAP Assignment Request"];
bsc_gscon <= mgw_msc [label="BSSMAP Assignment Request"];
bsc_gscon abox bsc_gscon [label="ST_ASSIGNMENT_\nWAIT_LCHAN"];
gscon <= msc_ [label="BSSMAP Assignment Request"];
gscon note gscon [label="GSCON_EV_ASSIGNMENT_START\n data=struct assignment_request"];
gscon abox gscon [label="ST_ASSIGNMENT"];
ass <- gscon [label="assignment_fsm_start()"];
ass abox ass [label="ASSIGNMENT_ST_\nWAIT_LCHAN_ACTIVE"];
bsc_lchan <- bsc_gscon [label="lchan_select_by_chan_mode(chan_mode)"];
|||;
--- [label="IF returned lchan is NULL"];
bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
--- [label="On any error (no lchan, etc.)"];
ass box ass [label="on_assignment_failure()"];
ass => msc_ [label="BSSMAP Assignment Failure"];
ass abox ass [label="terminate"];
ass -> gscon [label="GSCON_EV_ASSIGNMENT_END"];
gscon abox gscon [label="ST_ACTIVE"];
---;
|||;
bsc_gscon box bsc_gscon [label="store lchan pointer in conn->lchan_for_assignment"];
bsc_lchan <- bsc_gscon [label="lchan_activate(FOR_ASSIGNMENT)"];
lchan abox lchan [label="UNUSED"];
ass box ass [label="conn->assignment.new_lchan = lchan_select_by_chan_mode()"];
lchan <- ass [label="lchan_activate(FOR_ASSIGNMENT)"];
lchan abox lchan [label="WAIT_TS_READY"];
lchan rbox lchan [label="most details omitted, see lchan_fsm and lchan_rtp_fsm diagrams"];
...;
|||;
--- [label="on lchan FSM error or timeout"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_gscon box bsc_gscon [label="'forget' all about conn->lchan_for_assignment"];
bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
lchan -> ass [label="ASSIGNMENT_EV_LCHAN_ERROR"];
ass box ass [label="on_assignment_failure()"];
ass rbox gscon [label="See 'On any error' above"];
--- [label="END: 'on error'"];
...;
...;
--- [label="IF lchan FSM decides that it is an lchan for speech"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_ENSURE_MGW_ENDPOINT"];
--- [label="IF there is an MGW endpoint for the BTS already (conn->user_plane.fi_bts)"];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];
--- [label="ELSE: no MGW endpoint for the BTS side yet"];
bsc_gscon abox bsc_gscon [label="ST_ASSIGNMENT_\nWAIT_CRCX_BTS"];
bsc_gscon box bsc_gscon [label="assignment_created_mgw_endpoint = true"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_create()"];
bsc_mgcp abox bsc_mgcp [label="ST_CRCX_RESP (MGCP_MGW_TIMEOUT = 4s)"];
bsc_mgcp => mgw_msc [label="CRCX (for BTS)"];
bsc_gscon note bsc_mgcp [label="conn FSM relies on mgcp FSM timeout"];
lchan abox lchan [label="LCHAN_ST_WAIT_ACTIV_ACK"];
ms <= lchan [label="RSL Chan Activ"];
...;
--- [label="On Timeout"];
bsc_mgcp note bsc_mgcp [label="On timeouit, the MGCP FSM will terminate, emitting the parent_term
event set upon mgcp_conn_create():"];
bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS"];
bsc_gscon note bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS is handled by the conn FSM allstate
handler. It sets conn->user_plane.fi_bts = NULL."];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_ERROR"];
bsc_lchan note bsc_gscon [label="conn FSM timeout handler exits and relies on the lchan FSM
signalling error, which should actually happen immediately:"];
bsc_gscon <- bsc_lchan [label="GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
bsc_gscon box bsc_gscon [label="'forget' all about conn->lchan_for_assignment"];
bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];
--- [label="END: 'On Timeout'"];
ms => lchan [label="RSL Chan Activ ACK"];
lchan -> ass [label="ASSIGNMENT_EV_LCHAN_ACTIVE"];
ass abox ass [label="ASSIGNMENT_ST_\nWAIT_RR_ASS_COMPLETE"];
ms <= ass [label="RR Assignment Command"];
lchan note ass [label="The lchan FSM will continue with RSL and RTP while the Assignment FSM waits.
ASSIGNMENT_EV_LCHAN_ESTABLISHED means that both RSL and RTP are established.
Usually, RTP will be done first, and the ASSIGNMENT_EV_LCHAN_ESTABLISHED may be
received even before ASSIGNMENT_EV_RR_ASSIGNMENT_COMPLETE.
assignment_fsm_wait_lchan_established_onenter() decides whether to wait or not."];
...;
ms => lchan [label="RSL EST IND"];
lchan -> ass [label="ASSIGNMENT_EV_LCHAN_ESTABLISHED",ID="(may come as early as this, or...)"];
ms => ass [label="RR Assignment Complete (came with EST IND)"];
ass abox ass [label="ASSIGNMENT_ST_\nWAIT_LCHAN_ESTABLISHED"];
--- [label="IF lchan is not in LCHAN_ST_ESTABLISHED yet (waiting for RTP)"];
...;
lchan rbox lchan [label="when lchan RTP FSM is done with setting up RTP"];
lchan -> ass [label="ASSIGNMENT_EV_LCHAN_ESTABLISHED",ID="(...may come only now)"];
---;
ass abox ass [label="ASSIGNMENT_ST_WAIT_\nMGW_ENDPOINT_TO_MSC"];
ass -> gscon [label="gscon_connect_mgw_to_msc()"];
...;
ass <- gscon [label="ASSIGNMENT_EV_MSC_MGW_OK"];
ass box ass [label="assignment_success()"];
ass => msc_ [label="BSSMAP Assignment Complete"];
ass -> gscon [label="gscon_change_primary_lchan()"];
lchan <- gscon [label="LCHAN_RTP_EV_ESTABLISHED"];
ass abox ass [label="terminate"];
ass -> gscon [label="GSCON_EV_ASSIGNMENT_END"];
gscon abox gscon [label="ST_ACTIVE"];
bsc_mgcp <= mgw_msc [label="CRCX OK (for BTS)"];
bsc_mgcp box bsc_mgcp [label="libosmo-mgcp-client fsm_crcx_resp_cb()"];
bsc_mgcp abox bsc_mgcp [label="ST_READY"];
bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_CRCX_RESP_BTS"];
bsc_gscon abox bsc_gscon [label="ST_ASSIGNMENT_\nWAIT_LCHAN"];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];
--- [label="END: lchan FSM decides that it is an lchan for speech"];
...;
...;
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ACTIVE"];
bsc_gscon abox bsc_gscon [label="ST_ASSIGNMENT_\nWAIT_COMPLETE\nT10, 6s"];
ms <= bsc_gscon [label="RR Assignment"];
...;
--- [label="On Timeout"];
bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_LCHAN_RELEASE"];
bsc_gscon box bsc_gscon [label="'forget' all about conn->lchan_for_assignment"];
--- [label="IF assignment_created_mgw_endpoint == true"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];
bsc_gscon note bsc_mgcp [label="If the MGW endpoint didn't exist before the Assignment, release
it now. If there was one before this, it is probably still in use by a previous lchan, so
keep it in place."];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
--- [label="END: 'On Timeout'"];
...;
ms => bsc_gscon [label="RR Assignment Complete"];
bsc_gscon -> bsc_lchan [label="OLD lchan: LCHAN_EV_LCHAN_RELEASE"];
bsc_gscon box bsc_gscon [label="conn->lchan = conn->lchan_for_assignment"];
--- [label="IF: chan_mode a speech mode?"];
bsc_gscon abox bsc_gscon [label="ST_WAIT_MDCX_BTS"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_modify()"];
bsc_mgcp note bsc_mgcp [label="same mgcp FSM as above, for BTS side"];
bsc_mgcp abox bsc_mgcp [label="ST_MDCX_RESP"];
bsc_mgcp => mgw_msc [label="MDCX (for BTS)"];
...;
--- [label="On Timeout"];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_RELEASE"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];
bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];
bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];
bsc_gscon => mgw_msc [label="BSSMAP Clear Request"];
--- [label="END: 'On Timeout'"];
...;
bsc_mgcp <= mgw_msc [label="MDCX OK"];
bsc_mgcp abox bsc_mgcp [label="ST_READY"];
bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_MDCX_RESP_BTS"];
bsc_gscon abox bsc_gscon [label="ST_WAIT_CRCX_MSC"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_create()"];
bsc_mgcp note bsc_mgcp [label="second mgcp FSM for MSC side"];
bsc_mgcp => mgw_msc [label="CRCX (for MSC)"];
...;
--- [label="On Timeout"];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_RELEASE"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];
bsc_gscon => mgw_msc [label="BSSMAP Assignment Failure"];
bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];
bsc_gscon => mgw_msc [label="BSSMAP Clear Request"];
--- [label="END: 'On Timeout'"];
...;
bsc_mgcp <= mgw_msc [label="CRCX OK (for MSC)"];
bsc_gscon <- bsc_mgcp [label="GSCON_EV_MGW_CRCX_RESP_MSC"];
--- [label="END: chan_mode a speech mode?"];
bsc_gscon => mgw_msc [label="BSSMAP Assignment Complete"];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
}

View File

@ -0,0 +1,42 @@
digraph G {
rankdir=TB
labelloc=t; label="Handover FSM: Inter-BSC Incoming"
old_bss [label="old BSS",shape=box3d]
msc [label="MSC",shape=box3d]
ho_in [label="inter-BSC HO Incoming",shape=box]
gscon [label="gscon FSM",shape=box3d]
lchan [label="lchan FSM",shape=box3d]
msc2 [label="msc",shape=box3d]
old_bsc2 [label="old BSC",shape=box3d]
old_lchan [label="old lchan",shape=box3d]
terminate [shape=octagon]
old_bss -> msc [label="BSSMAP Handover Required",style=dotted]
msc -> ho_in [label="BSSMAP Handover Request",style=dotted]
ho_in -> gscon [label="GSCON_EV_A_CONN_IND\nBSSMAP Handover Request",style=dotted]
gscon -> HO_ST_WAIT_LCHAN_ACTIVE [label="handover_start_inter_bsc_in()",style=dotted]
HO_ST_WAIT_LCHAN_ACTIVE -> lchan [label="lchan_activate()\nFOR_HANDOVER",style=dotted]
lchan -> HO_ST_WAIT_LCHAN_ACTIVE [label="HO_EV_\nLCHAN_ACTIVE,\n_ERROR",style=dotted,constraint=false]
HO_ST_WAIT_LCHAN_ACTIVE -> HO_ST_WAIT_RR_HO_DETECT
HO_ST_WAIT_RR_HO_DETECT -> msc2 [label="BSSMAP\nHandover\nAccept\nwith\nRR Handover\nCommand",style=dotted]
msc2 -> old_bsc2 -> old_lchan [label="RR Handover\nCommand",style=dotted]
old_lchan -> lchan [label="MS moves",style=dotted,constraint=false]
lchan -> HO_ST_WAIT_RR_HO_DETECT [label="RR Handover\nDetect",style=dotted]
HO_ST_WAIT_RR_HO_DETECT -> WAIT_RR_HO_COMPLETE
lchan -> WAIT_RR_HO_COMPLETE [label="RR Handover\nComplete",style=dotted]
WAIT_RR_HO_COMPLETE -> WAIT_LCHAN_ESTABLISHED
lchan -> WAIT_LCHAN_ESTABLISHED [label="HO_EV_LCHAN_\nESTABLISHED",style=dotted]
WAIT_LCHAN_ESTABLISHED -> terminate [label="non-TCH"]
WAIT_LCHAN_ESTABLISHED -> WAIT_MGW_ENDPOINT_TO_MSC
WAIT_MGW_ENDPOINT_TO_MSC -> terminate [label="handover_end()"]
terminate -> msc2 [label="BSSMAP Handover\nComplete\n/ Failure",style=dotted,constraint=false]
err [label="on error",shape=box,style=dashed]
err -> terminate [style=dashed]
}

View File

@ -0,0 +1,74 @@
msc {
hscale=2;
ms [label="MS/BTS"], lchan[label="BSC lchan FSM"], ho[label="BSC Handover FSM"],
gscon[label="BSC conn FSM"], msc_[label="MSC"];
ms note msc_ [label="inter-BSC Handover Incoming"];
gscon <= msc_ [label="N-Connect: BSSMAP Handover Request"];
gscon box gscon [label="bsc_subscr_con_allocate()"];
gscon abox gscon [label="ST_INIT"];
gscon -> gscon [label="GSCON_EV_A_CONN_IND"];
ho <- gscon [label="handover_start_inter_bsc_in()"];
ho abox ho [label="allocate\nHO_ST_NOT_STARTED"];
ho box ho [label="lchan_select_by_chan_mode()"];
ho abox ho [label="HO_ST_WAIT_\nLCHAN_ACTIVE"];
lchan <- ho [label="lchan_activate(FOR_HANDOVER)"];
lchan rbox lchan [label="(most details omitted, see lchan_fsm diagrams)"];
...;
...;
--- [label="On any error or timeout"];
ho box ho [label="handover_end(fail)"];
ho -> gscon [label="GSCON_EV_HANDOVER_END"];
gscon note msc_ [label="There is no specific BSSMAP Handover Request NACK message."];
gscon => msc_ [label="BSSMAP Clear Request"];
gscon abox gscon [label="ST_CLEARING"];
gscon rbox msc_ [label="the usual disconnect dance"];
--- [label="END: 'On any error or timeout'"];
...;
...;
lchan abox lchan [label="LCHAN_ST_WAIT_\nACTIV_ACK"];
ms <= lchan [label="RSL Chan Activ"];
...;
ms => lchan [label="RSL Chan Activ ACK"];
lchan -> ho [label="HO_EV_LCHAN_ACTIVE"];
ho abox ho [label="HO_ST_WAIT_\nRR_HO_DETECT"];
ho => msc_ [label="BSSMAP Handover Request Acknowledge\nwith RR Handover Command"];
...;
ms => ho [label="RR Handover Detect\nHO_EV_RR_HO_DETECT"];
ho => msc_ [label="BSSMAP Handover Detect"];
ho abox ho [label="HO_ST_WAIT_\nRR_HO_COMPLETE"];
...;
lchan note ho [label="The lchan FSM will continue with RSL and RTP while the HO FSM waits.
HO_EV_LCHAN_ESTABLISHED means that both RSL and RTP are established.
Usually, RTP will be done first, and the HO_EV_LCHAN_ESTABLISHED may be
received even before HO_EV_RR_HO_COMPLETE.
ho_fsm_wait_lchan_established_onenter() decides whether to wait or not."];
...;
ms => lchan [label="RSL EST IND"];
lchan -> ho [label="HO_EV_LCHAN_ESTABLISHED",ID="(may come as early as this, or...)"];
ms => ho [label="RR Handover Complete (from EST IND)\n HO_EV_RR_HO_COMPLETE"];
ho abox ho [label="HO_ST_WAIT_\nLCHAN_ESTABLISHED"];
...;
lchan rbox lchan [label="when lchan FSM is done with setting up RTP"];
lchan -> ho [label="HO_EV_LCHAN_ESTABLISHED",ID="(...may come only now)"];
ho abox ho [label="HO_ST_WAIT_\nMGW_ENDPOINT_TO_MSC"];
ho -> gscon [label="gscon_connect_mgw_to_msc()"];
...;
ho <- gscon [label="HO_EV_MSC_MGW_OK"];
ho box ho [label="handover_end(OK)"];
ho => msc_ [label="BSSMAP Handover Complete"];
ho -> gscon [label="gscon_change_primary_lchan()"];
lchan <- gscon [label="LCHAN_RTP_EV_ESTABLISHED"];
ho -> gscon [label="GSCON_EV_HANDOVER_END"];
gscon abox gscon [label="ST_ACTIVE"];
ho box ho [label="detach from parent to not fire another meaningless GSCON_EV_HANDOVER_END"];
ho abox ho [label="terminate"];
}

View File

@ -1,37 +0,0 @@
msc {
hscale=2;
ms [label="MS via BTS"], bsc_lchan[label="BSC lchan FSM"], bsc_gscon[label="BSC conn FSM"],
msc_[label="MSC"];
ms note msc_ [label="inter-BSC Handover to another BSS"];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
bsc_gscon box bsc_gscon [label="bsc_handover_start(): init conn->ho"];
bsc_gscon -> bsc_gscon [label="GSCON_EV_HO_START (inter-BSC MO)"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MO_\nWAIT_HO_CMD\nT7"];
bsc_gscon => msc_ [label="BSSMAP Handover Required"];
...;
--- [label="On Timeout"];
ms note bsc_gscon [label="MS happily continues on the old lchan."];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
bsc_gscon box bsc_gscon [label="handover_end(fail)"];
--- [label="END: 'On Timeout'"];
...;
bsc_gscon <= msc_ [label="BSSMAP Handover Command"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MO_\nWAIT_CLEAR_CMD\nT8"];
ms <= bsc_gscon [label="RR Handover Command"];
...;
--- [label="On Timeout"];
ms note bsc_gscon [label="MS happily continues on the old lchan."];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
bsc_gscon box bsc_gscon [label="handover_end(fail)"];
--- [label="END: 'On Timeout'"];
...;
msc_ note msc_ [label="Remote BSS reported Handover Complete to the MSC, this connection has been
superseded."];
bsc_gscon <= msc_ [label="BSSMAP Clear Command"];
bsc_gscon abox bsc_gscon [label="ST_CLEARING"];
bsc_gscon => msc_ [label="BSSMAP Clear Complete"];
bsc_lchan <- bsc_gscon [label="LCHAN_EV_RELEASE"];
ms <=> bsc_lchan [label="release procedure (async)"];
}

View File

@ -1,154 +0,0 @@
msc {
hscale=3;
ms [label="MS via BTS"], bsc_lchan[label="BSC lchan FSM"], bsc_gscon[label="BSC conn FSM"],
bsc_mgcp[label="BSC mgcp FSM"], mgw_msc[label="MGW/MSC"];
ms note mgw_msc [label="inter-BSC Handover, from remote BSS"];
bsc_gscon <= mgw_msc [label="N-Connect: BSSMAP Handover Request"];
bsc_gscon box bsc_gscon [label="bsc_subscr_con_allocate()"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_WAIT_LCHAN"];
bsc_gscon box bsc_gscon [label="lchan_select_by_chan_mode()"];
bsc_lchan <- bsc_gscon [label="lchan_activate(lchan, FOR_HANDOVER)"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_TS_READY"];
...;
--- [label="on no lchan, lchan FSM error or timeout"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_gscon box bsc_gscon [label="handover_end(fail)"];
bsc_gscon => mgw_msc [label="BSSMAP Handover Failure"];
ms note bsc_gscon [label="MS happily continues on the old lchan."];
--- [label="END: 'on error'"];
...;
--- [label="IF lchan FSM decides that it is an lchan for speech"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_MGW_ENDPOINT_AVAILABLE"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_ENSURE_MGW_ENDPOINT"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_CRCX_BTS"];
bsc_gscon box bsc_gscon [label="handover_created_mgw_endpoint = true"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_create()"];
bsc_mgcp => mgw_msc [label="CRCX (for BTS)"];
bsc_mgcp abox bsc_mgcp [label="ST_CRCX_RESP (MGCP_MGW_TIMEOUT = 4s)"];
bsc_gscon note bsc_mgcp [label="conn FSM relies on mgcp FSM timeout"];
...;
--- [label="On Timeout"];
bsc_mgcp note bsc_mgcp [label="On timeout, the MGCP FSM will terminate, emitting the parent_term
event set upon mgcp_conn_create():"];
bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS"];
bsc_gscon note bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS is handled by the conn FSM allstate
handler. It sets conn->user_plane.fi_bts = NULL."];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_ERROR"];
bsc_lchan note bsc_gscon [label="conn FSM error handler exits and relies on the lchan FSM
signalling error, which should actually happen immediately:"];
bsc_gscon <- bsc_lchan [label="GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];
bsc_gscon box bsc_gscon [label="handover_end(fail)"];
bsc_gscon => mgw_msc [label="BSSMAP Handover Failure"];
ms note bsc_gscon [label="MS happily continues on the old lchan."];
--- [label="END: 'On Timeout'"];
...;
bsc_mgcp <= mgw_msc [label="CRCX OK (for BTS)"];
bsc_mgcp box bsc_mgcp [label="libosmo-mgcp-client fsm_crcx_resp_cb()"];
bsc_mgcp abox bsc_mgcp [label="ST_READY"];
bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_CRCX_RESP_BTS"];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_ACTIV_ACK"];
bsc_gscon note bsc_gscon [label="MSC-side CRCX needs from Handover Required the RTP IP address
and port of the MSC's MGW; from MGW CRCX ACK (BTS) the conn->user_plane.mgw_endpoint; The
Call-ID, which we actually derive from the SCCP connection ID"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_WAIT_CRCX_MSC"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_create()"];
bsc_mgcp note bsc_mgcp [label="second mgcp FSM for MSC side"];
bsc_mgcp => mgw_msc [label="CRCX (for MSC)"];
...;
--- [label="On Timeout"];
bsc_mgcp note bsc_mgcp [label="On timeout, the MGCP FSM will terminate, emitting the parent_term
event set upon mgcp_conn_create():"];
bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_FAIL_MSC"];
bsc_gscon note bsc_gscon [label="GSCON_EV_MGW_FAIL_MSC is handled by the conn FSM allstate
handler. It sets conn->user_plane.fi_msc = NULL."];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_RELEASE"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete() (FSM for BTS)"];
bsc_gscon box bsc_gscon [label="handover_end(fail)"];
bsc_gscon => mgw_msc [label="BSSMAP Handover Failure"];
ms note bsc_gscon [label="MS happily continues on the old lchan."];
--- [label="END: 'On Timeout'"];
...;
bsc_mgcp <= mgw_msc [label="CRCX OK (for MSC)"];
bsc_gscon <- bsc_mgcp [label="GSCON_EV_MGW_CRCX_RESP_MSC"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_WAIT_LCHAN"];
--- [label="END: chan_mode a speech mode?"];
--- [label="END: lchan FSM decides that it is an lchan for speech"];
...;
...;
bsc_lchan note bsc_lchan [label="TODO: when does the MS send RLL Establish Ind? I guess like
this:"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_RLL_ESTABLISH"];
ms => bsc_lchan [label="RLL Establish Ind"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ACTIVE"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_\nWAIT_HO_ACCEPT\nsanity timer?"];
bsc_gscon box bsc_gscon [label="Compose RR Handover Command"];
bsc_gscon => mgw_msc [label="BSSMAP Handover Request Acknowledge"];
mgw_msc note mgw_msc [label="MSC forwards the RR HO Cmd to the remote BSS"];
...;
--- [label="On timeout"];
bsc_lchan <- bsc_gscon [label="NEW lchan: LCHAN_EV_RELEASE"];
ms <=> bsc_lchan [label="release procedure (async)"];
bsc_gscon box bsc_gscon [label="handover_end(fail)"];
bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];
bsc_gscon => mgw_msc [label="BSSMAP Clear Request"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];
ms note bsc_gscon [label="MS happily continues on the old lchan."];
--- [label="END: On timeout"];
...;
ms => bsc_gscon [label="RR Handover Accept"];
bsc_gscon => mgw_msc [label="BSSMAP Handover Detect"];
mgw_msc note mgw_msc [label="MSC switches call to new path"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_WAIT_SABM\nT3105"];
...;
ms => bsc_gscon [label="SABM"];
bsc_lchan note bsc_lchan [label="SABM: Layer 2 message containing ?"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_\nWAIT_MDCX_BTS\nT?"];
bsc_lchan note bsc_lchan [label="TODO: what is UA?"];
ms <= bsc_gscon [label="RR UA"];
bsc_gscon note bsc_gscon [label="TODO: at what point do we know the information needed for BTS
MDCX?"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_modify()"];
bsc_mgcp abox bsc_mgcp [label="ST_MDCX_RESP"];
bsc_mgcp => mgw_msc [label="MDCX (for BTS)"];
...;
--- [label="Should the Handover Complete arrive early"];
ms => bsc_gscon [label="RR Handover Complete"];
bsc_gscon box bsc_gscon [label="handover_complete_received = true"];
---;
...;
--- [label="On timeout of the mgcp FSM"];
bsc_gscon note mgw_msc [label="MGCP FSM terminates"];
bsc_gscon <- bsc_mgcp [label="GSCON_EV_MGW_FAIL_BTS"];
bsc_lchan note bsc_gscon [label="The phone has already taken on the new lchan, but now we happen
to not be able to use it. The only sensible thing is to end the conn."];
bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];
bsc_gscon => mgw_msc [label="BSSMAP Clear Request\n(Equipment Failure)"];
bsc_lchan <- bsc_gscon [label="NEW lchan: LCHAN_EV_RELEASE"];
ms <=> bsc_lchan [label="release procedure (async)"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];
--- [label="END: On timeout of the mgcp FSM"];
...;
bsc_mgcp <= mgw_msc [label="MDCX OK"];
bsc_mgcp abox bsc_mgcp [label="ST_READY"];
bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_MDCX_RESP_BTS"];
--- [label="IF !handover_complete_received"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_MT_WAIT_HO_COMPL\nT?"];
--- [label="ELSE"];
bsc_gscon -> bsc_gscon [label="gscon_handover_post_complete()"];
---;
...;
ms => bsc_gscon [label="RR Handover Complete"];
bsc_gscon box bsc_gscon [label="gscon_handover_post_complete()"];
bsc_gscon => mgw_msc [label="BSSMAP Handover Complete"];
bsc_gscon note bsc_gscon [label="handover_end(success), conn->ho = NULL"];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
}

View File

@ -0,0 +1,27 @@
digraph G {
rankdir=TB
labelloc=t; label="Handover FSM: Inter-BSC Outgoing"
invisible [style=invisible]
invisible -> ho_out [label="Measurement Report\nincluding neighbor\nBSS ARFCN",style=dotted]
ho_out [label="inter-BSC HO Outgoing",shape=box]
msc [label="MSC",shape=box3d]
new_bsc [label="new BSC",shape=box3d]
lchan [label="lchan",shape=box3d]
terminate [shape=octagon]
ho_out -> HO_OUT_ST_WAIT_HO_COMMAND [label="handover_start()"]
HO_OUT_ST_WAIT_HO_COMMAND -> msc [label="BSSMAP Handover\nRequired",style=dotted]
msc -> new_bsc [label="BSSMAP Handover\nRequest",style=dotted]
new_bsc -> msc [label="BSSMAP Handover\nRequest Ack",style=dotted]
msc -> HO_OUT_ST_WAIT_HO_COMMAND [label="BSSMAP Handover\nCommand",style=dotted]
HO_OUT_ST_WAIT_HO_COMMAND -> lchan [label="RR Handover\nCommand\nfrom new BSC",style=dotted]
HO_OUT_ST_WAIT_HO_COMMAND -> HO_OUT_ST_WAIT_CLEAR
msc -> HO_OUT_ST_WAIT_CLEAR [label="BSSMAP\nClear\nCommand",style=dotted]
HO_OUT_ST_WAIT_CLEAR -> terminate
}

View File

@ -0,0 +1,47 @@
msc {
hscale=2;
ms [label="MS/BTS"], ho[label="BSC Handover FSM"], gscon[label="BSC conn FSM"], msc_[label="MSC"];
ms note msc_ [label="inter-BSC Handover to another BSS"];
gscon abox gscon [label="ST_ACTIVE"];
ms => ho [label="Measurement Report"];
ho box ho [label="Handover Decision"];
ho box ho [label="handover_request\n(struct handover_out_req)"];
ho note gscon [label="To make sure the conn FSM permits a handover, trigger an event:"];
ho -> gscon [label="GSCON_EV_HANDOVER_START\ndata=handover_out_req"];
gscon abox gscon [label="ST_HANDOVER"];
ho <- gscon [label="handover_start\n(handover_out_req)"];
ho box ho [label="handover_start_inter_bsc_out()"];
ho => msc_ [label="BSSMAP Handover Required"];
ho abox ho [label="HO_OUT_ST_WAIT_HO_COMMAND"];
...;
...;
--- [label="On Timeout"];
ho box ho [label="handover_end(fail)"];
ho -> gscon [label="GSCON_EV_HANDOVER_END"];
gscon abox gscon [label="ST_ACTIVE"];
ms note gscon [label="MS happily continues on the old lchan."];
--- [label="END: 'On Timeout'"];
...;
...;
ho <= msc_ [label="BSSMAP Handover Command\n HO_OUT_EV_BSSMAP_HO_COMMAND"];
ms <= ho [label="Forward L3 Info (RR Handover Command from new BSS)"];
ho abox ho [label="HO_OUT_ST_WAIT_CLEAR"];
...;
gscon abox gscon [label="ST_HANDOVER_MO_\nWAIT_CLEAR_CMD\nT8"];
ms <= gscon [label="RR Handover Command"];
...;
ho rbox gscon [label="On Timeout: same as above"];
...;
msc_ note msc_ [label="Remote BSS reported Handover Complete to the MSC,
this connection has been superseded."];
gscon <= msc_ [label="BSSMAP Clear Command\n GSCON_EV_A_CLEAR_CMD"];
gscon abox gscon [label="ST_CLEARING"];
gscon => msc_ [label="BSSMAP Clear Complete"];
...;
gscon <= msc_ [label="DISC IND\n GSCON_EV_A_DISC_IND"];
ho abox ho [label="terminate\n(child of conn FSM)"];
gscon abox gscon [label="terminate"];
}

View File

@ -0,0 +1,30 @@
digraph G {
rankdir=TB
labelloc=t; label="Handover FSM: Intra-BSC"
lchan [label="lchan FSM",shape=box3d]
intra [label="intra-BSC HO",shape=box]
old_lchan [label="old lchan",shape=box3d]
terminate [shape=octagon]
invisible [style="invisible"]
invisible -> intra [label="Measurement Report",style=dotted]
invisible -> old_lchan [style=invisible,arrowhead=none]
intra -> WAIT_LCHAN_ACTIVE [label="handover_start()",style=dotted]
WAIT_LCHAN_ACTIVE -> lchan [label="lchan_activate(FOR_HANDOVER)",style=dotted]
lchan -> WAIT_LCHAN_ACTIVE [label="HO_EV_\nLCHAN_\nACTIVE,ERROR",style=dotted,constraint=false]
WAIT_LCHAN_ACTIVE -> WAIT_RR_HO_DETECT
WAIT_RR_HO_DETECT -> old_lchan [label="RR Handover\nCommand",style=dotted,constraint=false]
lchan -> WAIT_RR_HO_DETECT [label="RR Handover\nDetect",style=dotted]
WAIT_RR_HO_DETECT -> WAIT_RR_HO_COMPLETE
lchan -> WAIT_RR_HO_COMPLETE [label="RR Handover\nComplete",style=dotted]
WAIT_RR_HO_COMPLETE -> WAIT_LCHAN_ESTABLISHED
lchan -> WAIT_LCHAN_ESTABLISHED [label="HO_EV_LCHAN_\nESTABLISHED",style=dotted]
WAIT_LCHAN_ESTABLISHED -> terminate [label="non-TCH"]
WAIT_LCHAN_ESTABLISHED -> WAIT_MGW_ENDPOINT_TO_MSC
WAIT_MGW_ENDPOINT_TO_MSC -> terminate [label="handover_end()"]
}

View File

@ -1,123 +1,82 @@
# Handover between cells, intra-BSC
msc {
hscale=3;
ms [label="MS via BTS"], bsc_lchan[label="BSC lchan FSM"], bsc_gscon[label="BSC conn FSM"],
bsc_mgcp[label="BSC mgcp FSM"], mgw_msc[label="MGW/MSC"];
hscale=2;
ms [label="MS via BTS"], lchan[label="BSC lchan FSM"], ho[label="BSC Handover FSM"],
gscon[label="BSC conn FSM"], msc_[label="MSC"];
ms note mgw_msc [label="intra-BSC Handover sequence"];
ms note msc_ [label="intra-BSC Handover"];
gscon abox gscon [label="ST_ACTIVE"];
ms => ho [label="Measurement Report"];
ho box ho [label="Handover Decision"];
ho box ho [label="handover_request\n(struct handover_out_req)"];
ho note gscon [label="To make sure the conn FSM permits a handover, trigger an event:"];
ho -> gscon [label="GSCON_EV_HANDOVER_START\ndata=handover_out_req"];
gscon abox gscon [label="ST_HANDOVER"];
ho <- gscon [label="handover_start\n(handover_out_req)"];
ho box ho [label="handover_start_intra_bsc()"];
ho abox ho [label="allocate\nHO_ST_NOT_STARTED"];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
bsc_gscon box bsc_gscon [label="bsc_handover_start(): init conn->ho"];
bsc_gscon -> bsc_gscon [label="GSCON_EV_HO_START (intra-BSC)"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_LCHAN"];
bsc_lchan <- bsc_gscon [label="lchan_activate(lchan, FOR_HANDOVER)"];
...;
--- [label="on lchan FSM error or timeout"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_gscon box bsc_gscon [label="handover_end(fail)"];
ms note bsc_gscon [label="MS happily continues on the old lchan."];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
--- [label="END: 'on error'"];
...;
--- [label="On any error or timeout"];
ho box ho [label="handover_end(fail)"];
ho -> gscon [label="GSCON_EV_HANDOVER_END"];
gscon abox gscon [label="ST_ACTIVE"];
ms note gscon [label="MS happily continues on the old lchan."];
--- [label="END: 'On any error or timeout'"];
...;
...;
--- [label="IF lchan FSM decides that it is an lchan for speech"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_ENSURE_MGW_ENDPOINT"];
--- [label="IF there is an MGW endpoint for the BTS already (conn->user_plane.fi_bts)"];
bsc_gscon box bsc_gscon [label="handover_created_mgw_endpoint = false"];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];
--- [label="ELSE: no MGW endpoint for the BTS side yet"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_CRCX_BTS"];
bsc_gscon box bsc_gscon [label="handover_created_mgw_endpoint = true"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_create()"];
bsc_mgcp => mgw_msc [label="CRCX (for BTS)"];
bsc_mgcp abox bsc_mgcp [label="ST_CRCX_RESP (MGCP_MGW_TIMEOUT = 4s)"];
bsc_gscon note bsc_mgcp [label="conn FSM relies on mgcp FSM timeout"];
...;
--- [label="On Timeout"];
bsc_mgcp note bsc_mgcp [label="On timeout, the MGCP FSM will terminate, emitting the parent_term
event set upon mgcp_conn_create():"];
bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS"];
bsc_gscon note bsc_gscon [label="GSCON_EV_MGW_FAIL_BTS is handled by the conn FSM allstate
handler. It sets conn->user_plane.fi_bts = NULL."];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_ERROR"];
bsc_lchan note bsc_gscon [label="conn FSM error handler exits and relies on the lchan FSM
signalling error, which should actually happen immediately:"];
bsc_gscon <- bsc_lchan [label="GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_gscon box bsc_gscon [label="handover_end(fail)"];
--- [label="IF handover_created_mgw_endpoint == true"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];
---;
ms note bsc_gscon [label="MS happily continues on the old lchan."];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
--- [label="END: 'On Timeout'"];
...;
ho box ho [label="lchan_select_by_type()"];
ho abox ho [label="HO_ST_WAIT_\nLCHAN_ACTIVE"];
lchan <- ho [label="lchan_activate(FOR_HANDOVER)"];
lchan rbox lchan [label="(most details omitted, see lchan_fsm diagrams)"];
bsc_mgcp <= mgw_msc [label="CRCX OK (for BTS)"];
bsc_mgcp box bsc_mgcp [label="libosmo-mgcp-client fsm_crcx_resp_cb()"];
bsc_mgcp abox bsc_mgcp [label="ST_READY"];
bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_CRCX_RESP_BTS"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_LCHAN"];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];
--- [label="END: lchan FSM decides that it is an lchan for speech"];
...;
...;
--- [label="On lchan error or timeout"];
lchan -> ho [label="HO_EV_LCHAN_ERROR"];
ho rbox gscon [label="same as above"];
--- [label="END: 'On lchan error or timeout'"];
...;
...;
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ACTIVE"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_DETECT\nT3103"];
bsc_gscon box bsc_gscon [label="gsm48_send_ho_cmd()"];
ms <= bsc_gscon [label="RR Handover Command"];
lchan abox lchan [label="LCHAN_ST_WAIT_ACTIV_ACK"];
ms <= lchan [label="RSL Chan Activ"];
...;
--- [label="On timeout"];
bsc_lchan <- bsc_gscon [label="NEW lchan: LCHAN_EV_RELEASE"];
ms <=> bsc_lchan [label="release procedure (async)"];
bsc_gscon box bsc_gscon [label="handover_end(fail)"];
--- [label="IF handover_created_mgw_endpoint == true"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];
---;
ms note bsc_gscon [label="MS happily continues on the old lchan."];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
--- [label="END: On timeout"];
ms => lchan [label="RSL Chan Activ ACK"];
lchan -> ho [label="HO_EV_LCHAN_ACTIVE"];
ho abox ho [label="HO_ST_WAIT_\nRR_HO_DETECT"];
...;
ms => bsc_gscon [label="RR Handover Detect"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_MDCX_BTS\ncontinue T3103"];
bsc_gscon -> bsc_lchan [label="OLD lchan: LCHAN_EV_RELEASE"];
ms <=> bsc_lchan [label="release procedure (async)"];
bsc_lchan note bsc_gscon [label="officially take over new lchan: conn->lchan = ho->new_lchan"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_modify()"];
bsc_mgcp note bsc_mgcp [label="mgcp FSM that was established for old lchan, for BTS side"];
bsc_mgcp abox bsc_mgcp [label="ST_MDCX_RESP"];
bsc_mgcp => mgw_msc [label="MDCX (for BTS)"];
ms => ho [label="RR Handover Detect\nHO_EV_RR_HO_DETECT"];
lchan note ho [label="At this point we should start to switch the MGW over to the new lchan.
But this is not implemented yet, as was not before introducing these FSMs."];
ho abox ho [label="HO_ST_WAIT_\nRR_HO_COMPLETE"];
...;
--- [label="Should the Handover Complete arrive early"];
ms => bsc_gscon [label="RR Handover Complete"];
bsc_gscon box bsc_gscon [label="handover_complete_received = true"];
---;
lchan note ho [label="The lchan FSM will continue with RSL and RTP while the HO FSM waits.
HO_EV_LCHAN_ESTABLISHED means that both RSL and RTP are established.
Usually, RTP will be done first, and the HO_EV_LCHAN_ESTABLISHED may be
received even before HO_EV_RR_HO_COMPLETE.
ho_fsm_wait_lchan_established_onenter() decides whether to wait or not."];
...;
--- [label="On timeout of the mgcp FSM"];
bsc_gscon note mgw_msc [label="MGCP FSM terminates"];
bsc_gscon <- bsc_mgcp [label="GSCON_EV_MGW_FAIL_BTS"];
bsc_lchan note bsc_gscon [label="The phone has already taken on the new lchan, but now we happen
to not be able to use it. The only sensible thing is to end the conn."];
bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];
bsc_gscon => mgw_msc [label="BSSMAP Clear Request\n(Equipment Failure)"];
bsc_lchan <- bsc_gscon [label="NEW lchan: LCHAN_EV_RELEASE"];
ms <=> bsc_lchan [label="release procedure (async)"];
bsc_gscon -> bsc_mgcp [label="mgcp_conn_delete()"];
ms => lchan [label="RSL EST IND"];
lchan -> ho [label="HO_EV_LCHAN_ESTABLISHED",ID="(may come as early as this, or...)"];
ms => ho [label="RR Handover Complete (from EST IND)\n HO_EV_RR_HO_COMPLETE"];
ho abox ho [label="HO_ST_WAIT_\nLCHAN_ESTABLISHED"];
...;
bsc_mgcp <= mgw_msc [label="MDCX OK"];
bsc_mgcp abox bsc_mgcp [label="ST_READY"];
bsc_mgcp -> bsc_gscon [label="GSCON_EV_MGW_MDCX_RESP_BTS"];
--- [label="IF !handover_complete_received"];
bsc_gscon abox bsc_gscon [label="ST_HANDOVER_\nWAIT_COMPLETE\ncontinue T3103"];
--- [label="ELSE"];
bsc_gscon -> bsc_gscon [label="gscon_handover_post_complete()"];
---;
lchan rbox lchan [label="when lchan FSM is done with setting up RTP"];
lchan -> ho [label="HO_EV_LCHAN_ESTABLISHED",ID="(...may come only now)"];
ho abox ho [label="HO_ST_WAIT_\nMGW_ENDPOINT_TO_MSC"];
ho -> gscon [label="gscon_connect_mgw_to_msc()"];
...;
ms => bsc_gscon [label="RR Handover Complete"];
bsc_gscon box bsc_gscon [label="gscon_handover_post_complete()"];
bsc_gscon note bsc_gscon [label="handover_end(success), conn->ho = NULL"];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
ho <- gscon [label="HO_EV_MSC_MGW_OK"];
ho box ho [label="handover_end(OK)"];
ho -> gscon [label="gscon_change_primary_lchan()"];
lchan <- gscon [label="LCHAN_RTP_EV_ESTABLISHED"];
ho -> gscon [label="GSCON_EV_HANDOVER_END"];
gscon abox gscon [label="ST_ACTIVE"];
ho box ho [label="detach from parent to not fire another meaningless GSCON_EV_HANDOVER_END"];
ho abox ho [label="terminate"];
}

View File

@ -1,38 +1,22 @@
digraph G {
rankdir=TB;
rankdir=TB
labelloc=t; label="lchan FSM"
invisible [style="invisible"]
UNUSED [penwidth=3.0]
WAIT_TS_READY
WAIT_MGW_ENDPOINT_AVAILABLE
WAIT_ACTIV_ACK
WAIT_IPACC_CRCX_ACK
WAIT_IPACC_MDCX_ACK
WAIT_RLL_ESTABLISH
ACTIVE [penwidth=3.0]
WAIT_SAPIS_RELEASED
WAIT_BEFORE_RF_RELEASE
WAIT_RF_RELEASE_ACK
WAIT_AFTER_ERROR
BORKEN
ESTABLISHED [penwidth=3.0]
ts [label="timeslot FSM",shape=box3d];
gscon [label="conn FSM",shape=box3d];
ts [label="timeslot FSM",shape=box3d]
rtp [label="lchan_rtp\nFSM",shape=box3d]
UNUSED -> WAIT_TS_READY [label="lchan_allocate()"]
WAIT_TS_READY -> WAIT_ACTIV_ACK
WAIT_ACTIV_ACK -> WAIT_RLL_ESTABLISH
WAIT_RLL_ESTABLISH -> WAIT_MGW_ENDPOINT_AVAILABLE [label="TCH"]
WAIT_MGW_ENDPOINT_AVAILABLE -> WAIT_IPACC_CRCX_ACK [label="IPACC BTS"]
WAIT_MGW_ENDPOINT_AVAILABLE -> ACTIVE
WAIT_IPACC_CRCX_ACK -> WAIT_IPACC_MDCX_ACK
WAIT_IPACC_MDCX_ACK -> ACTIVE
WAIT_RLL_ESTABLISH -> ACTIVE [label="non-TCH"];
WAIT_RLL_ESTABLISH -> WAIT_RF_RELEASE_ACK [label="timeout",style=dashed,constraint=false]
WAIT_ACTIV_ACK -> WAIT_RLL_RTP_ESTABLISH
WAIT_RLL_RTP_ESTABLISH -> ESTABLISHED
ACTIVE -> WAIT_SAPIS_RELEASED [label="LCHAN_EV_\nRELEASE"]
WAIT_SAPIS_RELEASED -> WAIT_BEFORE_RF_RELEASE
WAIT_SAPIS_RELEASED -> WAIT_RF_RELEASE_ACK [label="timeout",style=dashed,constraint=false]
ESTABLISHED -> WAIT_RLL_RTP_RELEASED [label="LCHAN_EV_\nRELEASE"]
WAIT_RLL_RTP_RELEASED -> WAIT_BEFORE_RF_RELEASE
WAIT_RLL_RTP_RELEASED -> WAIT_RF_RELEASE_ACK [label="timeout",style=dashed,constraint=false]
WAIT_BEFORE_RF_RELEASE -> WAIT_RF_RELEASE_ACK [label="T3111"]
WAIT_RF_RELEASE_ACK -> UNUSED
@ -43,11 +27,15 @@ rankdir=TB;
UNUSED -> ts [label="TS_EV_\nLCHAN_\nUNUSED",style=dotted,penwidth=3]
ts -> WAIT_TS_READY [label="LCHAN_EV_\nTS_READY",style=dotted]
WAIT_TS_READY -> rtp [label="TCH",style=dotted]
WAIT_TS_READY -> UNUSED [label="error/timeout",style=dashed,constraint=false]
{WAIT_ACTIV_ACK,WAIT_RF_RELEASE_ACK} -> BORKEN [label="error/timeout",style=dashed]
{WAIT_MGW_ENDPOINT_AVAILABLE,WAIT_IPACC_CRCX_ACK,WAIT_IPACC_MDCX_ACK} -> WAIT_SAPIS_RELEASED [label=error,style=dashed]
BORKEN -> WAIT_AFTER_ERROR [label="late RF Release ACK"]
WAIT_RLL_RTP_ESTABLISH -> WAIT_RLL_RTP_RELEASED [label=error,style=dashed]
WAIT_TS_READY -> gscon [label="GSCON_EV_\nENSURE_\nMGW_ENDPOINT",style=dotted]
gscon -> WAIT_MGW_ENDPOINT_AVAILABLE [label="LCHAN_EV_\nMGW_ENDPOINT_\n{AVAILABLE,ERROR}",style=dotted]
WAIT_ACTIV_ACK -> rtp [label="LCHAN_RTP_EV_LCHAN_READY",style=dotted]
rtp -> WAIT_RLL_RTP_ESTABLISH [label="LCHAN_EV_RTP_READY",style=dotted]
rtp -> ESTABLISHED [label="LCHAN_EV_RTP_RELEASED",style=dotted]
}

View File

@ -1,83 +0,0 @@
msc {
hscale=2;
ms [label="MS"], bts [label="BTS"], bsc[label="BSC"], bsc_lchan[label="BSC lchan FSM"],
bsc_gscon[label="BSC conn FSM"], msc_[label="MSC"];
ms note bsc_gscon [label="various lchan release scenarios"];
ms rbox msc_ [label="MSC releases"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];
bsc_gscon abox bsc_gscon [label="ST_ACTIVE"];
bsc_gscon <= msc_ [label="BSSMAP Clear Command"];
bsc_gscon abox bsc_gscon [label="ST_CLEARING"];
bsc_gscon => msc_ [label="BSSMAP Clear Complete"];
bsc_gscon -> bsc_lchan [label="LCHAN_EV_RELEASE"];
--- [label="IF SAPIs besides SAPI[0] are active"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nSAPIS_RELEASED\nT3109"];
bts <= bsc_lchan [label="RSL Release Request (Local End)..."];
bts <= bsc_lchan [label="...for each SAPI, except link_id=0"];
ms <= bsc_lchan [label="RR Channel Release"];
bts <= bsc_lchan [label="RSL Deactivate SACCH",ID="if appropriate pchan"];
...;
bts => bsc_lchan [label="RSL Release ACKs"];
--- [label="END: SAPIs besides SAPI[0] are active"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nBEFORE_RF_RELEASE\nT3111"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_FORGET_LCHAN"];
bsc_gscon note bsc_gscon [label="has already forgotten the lchan above."];
...;
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRF_RELEASE_ACK\n4s"];
bts <= bsc_lchan [label="RSL RF Channel Release"];
...;
bts => bsc_lchan [label="RSL RF Channel Release ACK"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];
...;
...;
ms rbox msc_ [label="BSC releases, outside of conn FSM's flow"];
bsc -> bsc_lchan [label="LCHAN_EV_RELEASE"];
--- [label="IF SAPIs besides SAPI[0] are active"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nSAPIS_RELEASED\nT3109"];
bts <= bsc_lchan [label="RSL Release Request (Local End)..."];
bts <= bsc_lchan [label="...for each SAPI, except link_id=0"];
ms <= bsc_lchan [label="RR Channel Release",ID="if conn is present"];
bts <= bsc_lchan [label="RSL Deactivate SACCH",ID="if appropriate pchan"];
...;
bts => bsc_lchan [label="RSL Release ACKs"];
--- [label="END: SAPIs besides SAPI[0] are active"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nBEFORE_RF_RELEASE\nT3111"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_FORGET_LCHAN"];
bsc_gscon note bsc_gscon [label="conn FSM notices that its primary lchan is gone"];
bsc_gscon => msc_ [label="BSSMAP Clear Request"];
bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];
...;
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRF_RELEASE_ACK\n4s"];
bts <= bsc_lchan [label="RSL RF Channel Release"];
...;
bts => bsc_lchan [label="RSL RF Channel Release ACK"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];
...;
bsc_gscon <= msc_ [label="BSSMAP Clear Command"];
bsc_gscon abox bsc_gscon [label="ST_CLEARING"];
bsc_gscon => msc_ [label="BSSMAP Clear Complete"];
...;
...;
ms rbox msc_ [label="MS releases"];
ms => bts [label="DISC"];
bts => bsc_lchan [label="RLL Release Ind..."];
bts => bsc_lchan [label="...for each SAPI"];
bsc_lchan note bsc_lchan [label="The lchan FSM notices when all SAPIs have been released"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nBEFORE_RF_RELEASE\nT3111"];
...;
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRF_RELEASE_ACK\n4s"];
bts <= bsc_lchan [label="RSL RF Channel Release"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_FORGET_LCHAN"];
bsc_gscon note bsc_gscon [label="conn FSM notices that its primary lchan is gone"];
bsc_gscon => msc_ [label="BSSMAP Clear Request"];
bsc_gscon abox bsc_gscon [label="ST_WAIT_CLEAR_CMD"];
...;
bts => bsc_lchan [label="RSL RF Channel Release ACK"];
...;
bsc_gscon <= msc_ [label="BSSMAP Clear Command"];
bsc_gscon => msc_ [label="BSSMAP Clear Complete"];
}

44
doc/lchan-rtp-fsm.dot Normal file
View File

@ -0,0 +1,44 @@
digraph G {
rankdir=TB
labelloc=t; label="lchan RTP FSM"
lchan [label="lchan\nFSM",shape=box3d]
lchan2 [label="lchan\nFSM",shape=box3d]
ho_as [label="Handover or Assignment FSM",shape=box3d]
invisible [style=invisible]
ho [label="Handover FSM",shape=box3d]
mgwep [label="mgw endpoint\nFSM",shape=box3d]
start [label="lchan_rtp_fsm_start()",shape=box]
WAIT_READY_TO_SWITCH_RTP [label="WAIT_READY_TO_SWITCH_RTP\nonly if wait_before_switching_rtp"]
terminate [shape=octagon]
lchan -> start [style=dashed]
start -> WAIT_MGW_ENDPOINT_AVAILABLE
start -> WAIT_LCHAN_READY [label="re-use existing\nendpoint CI"]
WAIT_MGW_ENDPOINT_AVAILABLE -> mgwep [label="gscon_ensure_mgw_endpoint()\nand CRCX to-BTS",style=dashed]
mgwep -> WAIT_MGW_ENDPOINT_AVAILABLE [label="LCHAN_RTP_EV_\nMGW_ENDPOINT_\n{AVAILABLE,ERROR}",style=dashed]
WAIT_MGW_ENDPOINT_AVAILABLE -> WAIT_LCHAN_READY
lchan -> WAIT_LCHAN_READY [label="LCHAN_RTP_EV_LCHAN_READY",style=dashed]
WAIT_LCHAN_READY -> WAIT_IPACC_CRCX_ACK [label="IPACC BTS"]
WAIT_LCHAN_READY -> WAIT_READY_TO_SWITCH_RTP
WAIT_IPACC_CRCX_ACK -> WAIT_IPACC_MDCX_ACK
WAIT_IPACC_MDCX_ACK -> WAIT_READY_TO_SWITCH_RTP
invisible -> ho [label="HO DETECT",style=dashed]
ho -> WAIT_READY_TO_SWITCH_RTP [label="LCHAN_RTP_EV_READY_TO_SWITCH",style=dashed]
WAIT_READY_TO_SWITCH_RTP -> WAIT_MGW_ENDPOINT_CONFIGURED
WAIT_MGW_ENDPOINT_CONFIGURED -> mgwep [label="MDCX",style=dashed]
mgwep -> WAIT_MGW_ENDPOINT_CONFIGURED [label="LCHAN_RTP_EV_\nMGW_ENDPOINT_\nCONFIGURED",style=dashed]
WAIT_MGW_ENDPOINT_CONFIGURED -> RTP_READY
RTP_READY -> lchan2 [label="LCHAN_EV_\nRTP_READY",style=dashed]
RTP_READY -> RTP_ESTABLISHED
lchan2 -> RTP_ESTABLISHED [label="LCHAN_RTP_EV_\nRELEASE",style=dashed]
RTP_ESTABLISHED -> terminate
RTP_READY -> RTP_ROLLBACK
RTP_ROLLBACK -> terminate
terminate -> lchan2 [label="LCHAN_EV_\nRTP_RELEASED",style=dashed]
lchan2 -> ho_as [label="XX_EV_LCHAN_\nESTABLISHED",style=dashed]
ho_as -> RTP_READY [label="LCHAN_RTP_EV_\n{ESTABLISHED,\nROLLBACK}",style=dashed]
}

View File

@ -1,306 +1,216 @@
msc {
hscale=2;
bts [label="MS/BTS"], bsc[label="BSC"], bsc_ts [label="BSC timeslot FSM"],
bsc_lchan[label="BSC lchan FSM"], bsc_gscon[label="BSC conn FSM"],
mgw_msc[label="MGW/MSC"];
ms [label="MS/BTS"], ts [label="BSC timeslot FSM"],
lchan[label="BSC lchan FSM"], rtp[label="BSC lchan RTP FSM"],mgwep[label="BSC MGW endpoint FSM"];
bts box mgw_msc [label="lchan allocation sequence"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];
ms box mgwep [label="lchan allocation sequence"];
lchan abox lchan [label="LCHAN_ST_UNUSED"];
...;
lchan rbox lchan [label="lchan_activate(activate_info)"];
lchan note lchan [label="Dispatching event to make sure the lchan FSM permits activation."];
lchan -> lchan [label="LCHAN_EV_ACTIVATE\ndata = activate_info"];
lchan abox lchan [label="LCHAN_ST_\nWAIT_TS_READY"];
ts <- lchan [label="TS_EV_LCHAN_REQUESTED"];
ts rbox ts [label="Most details omitted. See timeslot FSM diagrams."];
ts note ts [label="A dyn TS may be in PDCH mode and will asynchronously switch off PDCH first. A
non-dynamic TS is ready immediately."];
|||;
--- [label="IF requires_voice_stream"];
lchan -> rtp [label="lchan_rtp_fsm_start()"];
rtp abox rtp [label="allocate\n LCHAN_RTP_ST_\nWAIT_MGW_ENDPOINT_\nAVAILABLE"];
--- [label="IF no endpoint-CI yet"];
rtp box rtp [label="gscon_ensure_mgw_endpoint()"];
rtp -> mgwep [label="mgw_endpoint_ci_add(to-BTS)"];
rtp -> mgwep [label="CRCX to-BTS"];
mgwep rbox mgwep [label="MGCP: CRCX"];
...;
mgwep rbox mgwep [label="MGCP: CRCX OK"];
rtp <- mgwep [label="LCHAN_RTP_EV_MGW_ENDPOINT_AVAILABLE"];
rtp note mgwep [label="The CRCX OK has assigned us a new endpoint CI number"];
rtp abox rtp [label="LCHAN_RTP_ST_WAIT_LCHAN_READY"];
--- [label="END: no endpoint-CI yet"];
--- [label="END: requires_voice_stream"];
|||;
...;
ts -> lchan [label="LCHAN_EV_TS_READY"];
lchan abox lchan [label="LCHAN_ST_\nWAIT_ACTIV_ACK"];
--- [label="IF FOR_MS_CHANNEL_REQUEST"];
ms <= lchan [label="RSL Chan Activ (RSL_ACT_INTRA_IMM_ASS)"];
--- [label="ELSE: FOR_ASSIGNMENT"];
ms <= lchan [label="RSL Chan Activ (RSL_ACT_INTRA_NORM_ASS)"];
--- [label="ELSE: FOR_HANDOVER"];
ms <= lchan [label="RSL Chan Activ (RSL_ACT_INTER_ASYNC)"];
--- [label="END"];
...;
ms rbox lchan [label="On timeout or Chan Activ NACK, see: 'On any error', 'unrecoverable'"];
...;
ms => lchan [label="RSL Chan Activ ACK"];
lchan box lchan [label="lchan_fsm_post_activ_ack()"];
bts rbox mgw_msc [label="Channel Request from MS"];
bts => bsc [label="RSL Channel Request"];
bsc box bsc [label="lchan_select_by_type(chan_type)"];
bsc -> bsc_lchan [label="lchan_activate(lchan, FOR_MS_CHANNEL_REQUEST)"];
bsc_lchan rbox bsc_lchan [label="Continue at\nlchan_activate()\n"];
--- [label="IF FOR_MS_CHANNEL_REQUEST"];
ms <= lchan [label="RR Immediate Assignment"];
--- [label="ELSE: FOR_ASSIGNMENT"];
lchan rbox lchan [label="dispatch\nASSIGNMENT_EV_\nLCHAN_ACTIVE\n(see Assignment FSM diagrams)"];
ms <= lchan [label="RR Assignment Command"];
--- [label="ELSE: FOR_HANDOVER"];
lchan rbox lchan [label="dispatch\nHO_EV_LCHAN_ACTIVE\n(see Handover FSM diagrams)"];
--- [label="END"];
lchan abox lchan [label="LCHAN_ST_WAIT_\nRLL_RTP_ESTABLISH\nT3101"];
|||;
|||;
--- [label="IF requires_voice_stream"];
lchan -> rtp [label="LCHAN_RTP_EV_LCHAN_READY"];
|||;
--- [label="IF ip.access style BTS"];
rtp abox rtp [label="LCHAN_RTP_ST_WAIT_IPACC_CRCX_ACK"];
ms <= rtp [label="IPACC CRCX"];
...;
ms => rtp [label="IPACC CRCX ACK (BTS RTP port info)"];
rtp abox rtp [label="LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK"];
ms <= rtp [label="IPACC MDCX (MGW RTP port info)"];
...;
ms => rtp [label="IPACC MDCX ACK"];
--- [label="END ip.access style BTS"];
|||;
rtp box rtp [label="lchan_rtp_fsm_switch_rtp()"];
|||;
--- [label="IF wait_before_switching_rtp"];
rtp note rtp [label="During Handover, wait for HO DETECT before redirecting an existing endpoint
CI towards the new lchan."];
rtp abox rtp [label="LCHAN_RTP_ST_WAIT_READY_TO_SWITCH_RTP"];
...;
ms => rtp [label="HO DETECT (via Handover FSM)"];
--- [label="END: wait_before_switching_rtp"];
|||;
rtp abox rtp [label="LCHAN_RTP_ST_WAIT_MGW_ENDPOINT_CONFIGURED"];
rtp box rtp [label="connect_mgw_endpoint_to_lchan()"];
rtp -> mgwep [label="MDCX to-BTS"];
mgwep rbox mgwep [label="MGCP: MDCX"];
...;
mgwep rbox mgwep [label="MGCP: MDCX OK"];
rtp <- mgwep [label="LCHAN_RTP_EV_MGW_ENDPOINT_CONFIGURED"];
rtp abox rtp [label="LCHAN_RTP_ST_READY"];
lchan <- rtp [label="LCHAN_EV_RTP_READY"];
rtp note rtp [label="RTP FSM stays ready for Rollback until final establish event"];
...;
lchan -> rtp [label="LCHAN_RTP_EV_ESTABLISHED\nvia gscon_change_primary_lchan()"];
rtp abox rtp [label="LCHAN_RTP_ST_\nESTABLISHED"];
--- [label="END: requires_voice_stream"];
|||;
|||;
bts rbox mgw_msc [label="Channel Request from BSSMAP Assignment"];
bsc_gscon <= mgw_msc [label="BSSMAP Assignment request"];
bsc_gscon box bsc_gscon [label="lchan_select_by_chan_mode(chan_mode)"];
bsc_lchan <- bsc_gscon [label="lchan_activate(lchan, FOR_ASSIGNMENT)"];
bsc_lchan rbox bsc_lchan [label="Continue at\nlchan_activate()\n"];
|||;
|||;
bts rbox mgw_msc [label="Channel Request from Handover Decision"];
bsc note bsc [label="target lchan typically already chosen by Handover Decision"];
bsc -> bsc_gscon [label="GSCON_EV_HO_START (intra-BSC)"];
bsc_lchan <- bsc_gscon [label="lchan_activate(lchan, FOR_HANDOVER)"];
bsc_lchan rbox bsc_lchan [label="Continue at\nlchan_activate()\n"];
|||;
|||;
bts rbox mgw_msc [label="Channel Request from intra-BSC-MT-Handover"];
bsc_gscon <- mgw_msc [label="BSSMAP Handover Request"];
bsc_gscon box bsc_gscon [label="lchan_select_by_chan_mode(chan_mode)"];
bsc box bsc [label="lchan_activate(lchan, FOR_HANDOVER)"];
bsc_lchan rbox bsc_lchan [label="Continue at\nlchan_activate()\n"];
|||;
|||;
bts rbox mgw_msc [label="lchan_activate()"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_\nWAIT_TS_READY\n(timeout: ? s, Tnnnn)"];
|||;
|||;
--- [label="TCH?"];
bsc_lchan note bsc_gscon [label="This is skipped when FOR_MS_CHANNEL_REQUEST. If the MS requests
a TCH lchan, and we end up actually giving it a TCH because no SDCCH are available, we
can not set up an RTP stream because there is not even an L3 conn yet."];
bsc_lchan note bsc_gscon [label="The lchan FSM asks the conn FSM to have an MGW endpoint ready as
early as possible. Either the conn already has such MGW endpoint from a previous lchan,
in which case it immediately replies, or it requests one from the MGW, in which case we
wait for a response in 'TCH? (2)' below."];
bsc_lchan -> bsc_gscon [label="GSCON_EV_ENSURE_MGW_ENDPOINT"];
--- [label="IF conn has user_plane.fi_bts in state ST_READY"];
bsc_lchan <- bsc_gscon [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];
bsc_lchan box bsc_lchan [label="mgw_endpoint_available = true"];
bsc_lchan note bsc_lchan [label="lchan_activate() continues"];
--- [label="ELSE (no MGW endpoint available yet)"];
bsc_gscon => mgw_msc [label="CRCX (for BTS) via mgcp_conn_create()"];
bsc_gscon abox bsc_gscon [label="ST_WAIT_CRCX_BTS\n(timeout: ? s, Tnnnn)"];
bsc_lchan <- bsc_gscon [label="(event dispatch returns)"];
bsc_lchan note bsc_lchan [label="lchan_activate() continues"];
...;
bsc_gscon note bsc_gscon [label="async:"];
bsc_gscon <= mgw_msc [label="CRCX OK (for BTS)"];
bsc_lchan <- bsc_gscon [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];
bsc_lchan box bsc_lchan [label="mgw_endpoint_available = true"];
bsc_lchan note bsc_lchan [label="As soon as we reach LCHAN_ST_WAIT_MGW_ENDPOINT_AVAILABLE, this triggers
immedate action (s.b.), but until then, only the flag gets set to true."];
ms => lchan [label="RLL Establish Ind"];
lchan abox lchan [label="LCHAN_ST_\nESTABLISHED"];
lchan box lchan [label="lchan_on_fully_established()"];
--- [label="IF FOR_MS_CHANNEL_REQUEST"];
ms note lchan [label="No action required. The MS will have sent an L3 message in the RLL
Establish Ind and is then free to dispatch DTAP."];
--- [label="ELSE: FOR_ASSIGNMENT"];
lchan rbox lchan [label="dispatch\nASSIGNMENT_EV_\nLCHAN_ESTABLISHED\n(see Assignment FSM diagrams)"];
--- [label="ELSE: FOR_HANDOVER"];
lchan rbox lchan [label="dispatch\nHO_EV_LCHAN_ESTABLISHED\n(see Handover FSM diagrams)"];
--- [label="END"];
...;
--- [label="CRCX timeout"];
bsc_gscon note bsc_gscon [label="conn FSM should fire on CRCX timeout"];
bsc_lchan <- bsc_gscon [label="LCHAN_EV_MGW_ENDPOINT_ERROR"];
bsc_gscon note bsc_gscon [label="conn FSM should not assume anything and wait for
GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_lchan rbox bsc_lchan [label="Do 'On any error'"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];
bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED"];
--- [label="END: 'TCH?'"];
|||;
|||;
bsc_lchan box bsc_lchan [label="lchan_activate() exits"];
bsc_lchan note bsc_lchan [label="still in\nlchan_request()\nLCHAN_ST_WAIT_\nTS_READY"];
bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_REQUESTED"];
--- [label="IF requires_voice_stream"];
lchan rbox lchan [label="Assignment or Handover FSM:"];
lchan -> mgwep [label="CRCX/MDCX to-MSC"];
...;
--- [label="on error from TS or timeout:"];
bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_ERROR"];
bsc_lchan rbox bsc_lchan [label="Do 'On any error'"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];
bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED"];
---;
...;
bsc_ts abox bsc_ts [label="TS_ST_IN_USE"];
bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_READY"];
bsc_lchan box bsc_lchan [label="lchan_fsm_\npre_lchan_activ()"];
|||;
|||;
bts rbox mgw_msc [label="mode FOR_MS_CHANNEL_REQUEST"];
bts note bsc_lchan [label="This is the simple case where the MS requested a channel, and there is no
L3 conn to the MSC; no matter if this is SDDCH or a TCH channel type, we will not prepare
an RTP stream."];
bsc_lchan note bsc_lchan [label="still in lchan_fsm_\npre_lchan_activ()"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nACTIV_ACK\n(timeout: ? s, Tnnnn)"];
bts <= bsc_lchan [label="RSL Chan Activ (RSL_ACT_INTRA_IMM_ASS)"];
bts note bsc_lchan [label="If any errors occur from now on, we don't want to send an RR Immediate
Assignment Reject anymore."];
bsc_lchan box bsc_lchan [label="sent_chan_activ = true"];
...;
--- [label="on timeout"];
bsc_lchan rbox bsc_lchan [label="Continue at: 'On any error', 'unrecoverable'"];
---;
...;
bts => bsc_lchan [label="RSL Chan Activ ACK"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRLL_ESTABLISH\nT3101"];
bsc_lchan note bsc_lchan [label="Now the lchan is assigned, but has no L3 conn yet. On errors,
this will either go into graceful release or into broken state, but will not trigger any
events to a (non-existing) conn."];
...;
--- [label="on timeout"];
bts <= bsc_lchan [label="RSL RF Channel Release"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_RF_RELEASE_ACK\n(T?, 4s)"];
---;
...;
bts => bsc_lchan [label="RLL Establish Ind"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];
|||;
|||;
bts rbox mgw_msc [label="modes FOR_ASSIGNMENT and FOR_HANDOVER"];
bsc_lchan note bsc_lchan [label="still in lchan_fsm_\npre_lchan_activ()"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nACTIV_ACK\n(timeout: ? s, Tnnnn)"];
bts <= bsc_lchan [label="RSL Chan Activ (RSL_ACT_INTRA_NORM_ASS)",ID=FOR_ASSIGNMENT];
bts <= bsc_lchan [label="RSL Chan Activ (RSL_ACT_INTER_ASYNC)",ID=FOR_HANDOVER];
...;
--- [label="on timeout"];
bsc_lchan rbox bsc_lchan [label="Continue at: 'On any error', 'unrecoverable'"];
---;
bts => bsc_lchan [label="RSL Chan Activ ACK"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRLL_ESTABLISH\nT3101"];
...;
--- [label="on timeout"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_lchan -> bsc_lchan [label="lchan_fsm_pre_rf_release()"];
---;
...;
bts => bsc_lchan [label="RLL Establish Indication"];
|||;
--- [label="TCH? (2)"];
--- [label="mgw_endpoint_available == false?"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nMGW_ENDPOINT_\nAVAILABLE"];
bsc_lchan note bsc_lchan [label="rely on conn FSM timeout; apply only a long sanity timeout."];
...;
bsc_gscon <= mgw_msc [label="CRCX OK (for BTS)"];
bsc_lchan <- bsc_gscon [label="LCHAN_EV_MGW_ENDPOINT_AVAILABLE"];
bsc_lchan box bsc_lchan [label="mgw_endpoint_available = true"];
bsc_lchan <- bsc_lchan [label="re-invoke lchan_fsm_pre_lchan_activ()"];
--- [label="END: 'TCH? (2)'"];
|||;
--- [label="is BTS using IPA Abis? (osmo-bts, ip.access)"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nIPACC_CRCX_ACK\n(timeout: ? s, Tnnnn)"];
bts <= bsc_lchan [label="IPACC CRCX"];
...;
--- [label="on timeout"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_lchan -> bsc_lchan [label="lchan_graceful_release()"];
---;
...;
bts => bsc_lchan [label="IPACC CRCX ACK"];
bts note bsc_lchan [label="The IPACC CRCX ACK tells us what port the IPA Abis based BTS has
assigned to this lchan. AoIP: we need to forward this to the MGW (BTS side) with an MDCX;
SCCPlite: we forward this to the MSC during BSSMAP Assignment Complete (TODO: is this
correct??)"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nIPACC_MDCX_ACK\n(timeout: ? s, Tnnnn)"];
bts <= bsc_lchan [label="IPACC MDCX"];
bts note bsc_lchan [label="The IPACC MDCX tells IPA Abis based BTSes the IP address and RTP port
assigned by the BTS side of the MGW. AoIP: the MGW CRCX (BTS) must thus happen before
this; SCCPlite: the RTP port is already known from the timeslot+multiplex information."];
...;
--- [label="on timeout"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_lchan -> bsc_lchan [label="lchan_graceful_release()"];
---;
...;
bts => bsc_lchan [label="IPACC MDCX ACK"];
--- [label="END: is BTS using IPA Abis? (osmo-bts, ip.access)"];
|||;
bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];
bsc_lchan box bsc_lchan [label="lchan_fsm_post_lchan_activ()"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ACTIVE"];
bts <= bsc_gscon [label="RR Assignment",ID="BSSMAP Assignment Request"];
bts <= bsc_gscon [label="RR Handover Command",ID="intra-BSC HO"];
bsc_gscon => mgw_msc [label="BSSMAP Handover\nRequest Acknowledge",ID="inter-BSC-MT HO"];
...;
---[label="On error"];
bsc_lchan rbox bsc_lchan [label="Continue at 'When the lchan is no longer used'"];
---;
...;
bts => bsc_gscon [label="RR Assignment Complete",ID="BSSMAP Assignment Request"];
bts => bsc_gscon [label="RR Handover Detect",ID="intra-BSC HO"];
bts => bsc_gscon [label="RR Handover Accept",ID="inter-BSC-MT HO"];
bsc_gscon note bsc_gscon [label="conn FSM takes care of MGW endpoints for BTS side (possibly
redirect) and MSC side (possibly create). More information in e.g. assignment.msc and
handover.msc"];
lchan <- mgwep [label="OK"];
lchan box lchan [label="gscon_change_primary_lchan()"];
lchan -> rtp [label="LCHAN_RTP_EV_ESTABLISHED"];
rtp abox rtp [label="LCHAN_RTP_ST_\nESTABLISHED"];
rtp box rtp [label="Forget any Rollback info"];
--- [label="END: requires_voice_stream"];
...;
...;
...;
bts rbox mgw_msc [label="When the lchan is no longer used"];
--- [label="IF the MS or BTS release the lchan"];
bts -> bsc_lchan [label="RLL Release Ind for SAPI=0"];
--- [label="IF the BSC other than the conn FSM decides to release"];
bsc -> bsc_lchan [label="LCHAN_EV_RELEASE"];
--- [label="IF the MSC or conn FSM release the lchan"];
bsc_lchan <- bsc_gscon [label="LCHAN_EV_RELEASE"];
---;
bsc note bsc_gscon [label="The LCHAN_EV_RELEASE's data pointer possibly indicates an error
cause"];
bsc_lchan note bsc_gscon [label="If the conn FSM requested a release, it probably has already
forgotten about this lchan. However, if the MS/BTS initiated the release, make sure the conn FSM
is informed:"];
bsc_lchan box bsc_lchan [label="lchan_graceful_release()"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nSAPIS_RELEASED\nT3109"];
--- [label="TCH and got as far as Chan Activ Ack?"];
bts <= bsc_lchan [label="RSL Deactivate SACCH"];
---;
bts <= bsc_lchan [label="RLL Release Request (Local End)..."];
bts <= bsc_lchan [label="...for all SAPIs except [0]"];
|||;
--- [label="SAPI[0] in use?"];
bsc_lchan note bsc_lchan [label="for bts->nokia.no_loc_rel_cnf we do not expect Release Confirm
messages and this state immediately advances to lchan_fsm_pre_rf_release()"];
ms rbox mgwep [label="When the MS or BTS release the lchan"];
lchan abox lchan [label="LCHAN_ST_\nESTABLISHED"];
ms -> lchan [label="RLL Release Ind for SAPI=0"];
lchan abox lchan [label="LCHAN_ST_WAIT_RLL_RTP_RELEASED"];
lchan rbox lchan [label="Continue at 'common release' below"];
...;
--- [label="on timeout"];
bsc_lchan box bsc_lchan [label="Anyway try RF Channel Release, continue
with lchan_fsm_wait_before_rf_release()"];
---;
...;
bts => bsc_lchan [label="RLL Release Confirm..."];
bts => bsc_lchan [label="...for each SAPI except [0]"];
bsc_lchan box bsc_lchan [label="Stay in\nLCHAN_ST_WAIT_\nSAPIS_RELEASED\nuntil only SAPI[0] remains active"];
--- [label="END: 'SAPI[0] in use?'"];
|||;
ms rbox mgwep [label="When the BSC decides to release the lchan"];
lchan box lchan [label="lchan_release()"];
lchan abox lchan [label="LCHAN_ST_WAIT_RLL_RTP_RELEASED"];
ms <= lchan [label="RR Release"];
lchan rbox lchan [label="common release"];
--- [label="IF RTP FSM present"];
lchan -> rtp [label="LCHAN_RTP_EV_RELEASE"];
--- [label="END: RTP FSM present"];
ms <= lchan [label="RSL Deactivate SACCH"];
ms <= lchan [label="RSL Release Request (Local End)",ID="for each SAPI except [0]"];
lchan note lchan [label="for ms->nokia.no_loc_rel_cnf we do not expect Release Confirm
messages and immediately mark all SAPIs as released"];
bsc_lchan box bsc_lchan [label="lchan_fsm_wait_before_rf_release()"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nBEFORE_RF_RELEASE\nT3111"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_FORGET_LCHAN (data=lchan)"];
bsc_gscon note bsc_gscon [label="conn FSM immediately forgets about the lchan"];
bsc_gscon => mgw_msc [label="BSSMAP Clear Request?"];
...;
bsc_lchan box bsc_lchan [label="T3111 expires"];
bsc_lchan box bsc_lchan [label="lchan_fsm_pre_rf_release()"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRF_RELEASE_ACK\nT3111"];
bsc_lchan box bsc_lchan [label="for each bsc_rll_req matching this lchan: disable timer, call
cb(BSC_RLLR_IND_REL_IND)"];
bts <= bsc_lchan [label="RSL RF Channel Release"];
lchan <- rtp [label="LCHAN_EV_RTP_RELEASED"];
...;
--- [label="on timeout"];
bsc_lchan rbox bsc_lchan [label="Continue at: 'On any error', 'unrecoverable'"];
---;
ms => lchan [label="RLL Release Confirm",ID="for each SAPI except [0]"];
...;
bts => bsc_lchan [label="RSL RF Channel Release Ack"];
bsc_lchan box bsc_lchan [label="lchan_fsm_post_rf_release()"];
lchan box lchan [label="Stay in\nLCHAN_ST_WAIT_\nRLL_RTP_RELEASED\nuntil only SAPI[0] remains active"];
lchan abox lchan [label="LCHAN_ST_WAIT_\nBEFORE_RF_RELEASE\nT3111"];
...;
lchan box lchan [label="T3111 expires"];
lchan box lchan [label="lchan_fsm_pre_rf_release()"];
lchan abox lchan [label="LCHAN_ST_WAIT_\nRF_RELEASE_ACK\nT3111"];
ms <= lchan [label="RSL RF Channel Release"];
...;
lchan rbox lchan [label="On timeout, continue at: 'On any error', 'unrecoverable'"];
...;
ms => lchan [label="RSL RF Channel Release Ack"];
|||;
--- [label="IF an error cause was indicated on LCHAN_EV_RELEASE"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nAFTER_ERROR\n(timeout: T3111+2 s, T?)"];
--- [label="IF release_in_error"];
lchan abox lchan [label="LCHAN_ST_WAIT_\nAFTER_ERROR\n(timeout: T3111+2 s, T993111)"];
...;
bsc_lchan box bsc_lchan [label="timer expires"];
--- [label="END: 'an error cause was indicated on LCHAN_EV_RELEASE'"];
lchan box lchan [label="timer expires"];
--- [label="END: release_in_error"];
|||;
lchan abox lchan [label="LCHAN_ST_UNUSED"];
ts <- lchan [label="TS_EV_LCHAN_UNUSED"];
|||;
bsc_lchan box bsc_lchan [label="lchan_fsm_release_complete()"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];
bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED"];
bsc_ts abox bsc_ts [label="TS_ST_UNUSED"];
|||;
|||;
bts rbox mgw_msc [label="On any error"];
ms rbox mgwep [label="On any error"];
|||;
--- [label="IF FOR_MS_CHANNEL_REQUEST && !sent_chan_activ"];
bts <= bsc_lchan [label="RR Immediate Assign Reject"];
--- [label="IF FOR_MS_CHANNEL_REQUEST"];
ms <= lchan [label="RR Immediate Assign Reject"];
--- [label="ELSE: FOR_ASSIGNMENT"];
lchan rbox lchan [label="dispatch\nASSIGNMENT_EV_\nLCHAN_ERROR\n(see Assignment FSM diagrams)"];
--- [label="ELSE: FOR_HANDOVER"];
lchan rbox lchan [label="dispatch\nHO_EV_LCHAN_ERROR\n(see Handover FSM diagrams)"];
--- [label="END"];
|||;
--- [label="IF fi_rtp present"];
lchan -> rtp [label="LCHAN_RTP_EV_ROLLBACK"];
rtp rbox rtp [label="If to-BTS is not established yet, ROLLBACK is synonymous to LCHAN_RTP_EV_RELEASE"];
rtp rbox rtp [label="If there is no old_lchan, just DLCX instead"];
rtp abox rtp [label="LCHAN_RTP_ST_ROLLBACK"];
rtp box rtp [label="connect_mgw_endpoint_to_lchan()\nusing old_lchan"];
rtp -> mgwep [label="MDCX to-BTS"];
mgwep rbox mgwep [label="MGCP: MDCX"];
...;
mgwep rbox mgwep [label="MGCP: MDCX OK"];
rtp <- mgwep [label="LCHAN_RTP_EV_MGW_ENDPOINT_CONFIGURED"];
rtp abox rtp [label="terminate"];
lchan <- rtp [label="LCHAN_EV_RTP_RELEASED"];
--- [label="END: fi_rtp present"];
|||;
--- [label="IF FOR_ASSIGNMENT or FOR_HANDOVER"];
bsc_lchan -> bsc_gscon [label="GSCON_EV_LCHAN_ALLOC_ERROR"];
bsc_gscon note bsc_gscon [label="conn FSM shall immediately 'forget' the lchan"];
bsc_gscon => mgw_msc [label="BSSMAP\nAssignment Failure",ID=FOR_ASSIGNMENT];
bsc_gscon => mgw_msc [label="BSSMAP\nHandover Failure",ID="inter-BSC-MT HO"];
---;
|||;
--- [label="IF unrecoverable error"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_BORKEN"];
bsc_lchan note bsc_lchan [label="The broken state usually stays around
lchan abox lchan [label="LCHAN_ST_BORKEN"];
ms note lchan [label="The broken state usually stays around
until the BTS disconnects."];
...;
bts note bsc_lchan [label="If an ACK comes in late, for specific BTS models, we may choose to
ms note lchan [label="If an ACK comes in late, for specific BTS models, we may choose to
'repair' the lchan so that it is usable again."];
bts -> bsc_lchan [label="Chan Release ACK"];
bsc_lchan -> bsc_lchan [label="lchan_fsm_post_rf_release()"];
ms -> lchan [label="RF Chan Release ACK"];
lchan rbox lchan [label="continue above at\nLCHAN_ST_WAIT_\nAFTER_ERROR"];
}

View File

@ -0,0 +1,24 @@
digraph G {
rankdir=TB
labelloc=t; label="LEGEND FOR FSM GRAPHS"
box [label="function_call()\nputs FSM into state",shape="box"]
STATE [label="FSM_STATE"]
STATE2 [label="FSM_STATE"]
STATE3 [label="FSM_STATE"]
box -> STATE
STATE -> STATE2 [label="state transition"]
STATE2 -> STATE3
STATE -> STATE3 [label="transition\non error",style=dashed]
other [label="other FSM\ninstance\nor remote program",shape=box3d]
STATE2 -> other [label="event",style=dotted]
other -> STATE2 [label="event",style=dotted]
terminate [shape=octagon]
STATE3 -> terminate
err [label="common error\ntransition",shape=box,style=dashed]
err -> STATE3 [style=dashed]
}

View File

@ -0,0 +1,29 @@
msc {
A [label="FSM instance"],B [label="FSM instance"], C [label="remote program"];
|||;
||| [label="LADDER DIAGRAM LEGEND"];
|||;
A rbox C [label="Group Heading"];
A box A [label="function call or action"];
A -> B [label="event within program"];
B abox B [label="enter FSM state"];
B => C [label="network protocol message"];
...;
... [label="asynchronous wait time"];
...;
B <= C [label="network protocol message"];
|||;
||| [label="continue synchronously"];
|||;
A <- B [label="event within program"];
A rbox A [label="flow detail: 'continue at...'"];
...;
...;
--- [label="IF conditional"];
||| [label="..."];
--- [label="END: conditional"];
...;
B note B [label="arbitrary prose"];
}

24
doc/mgw-endpoint-fsm.dot Normal file
View File

@ -0,0 +1,24 @@
digraph G {
rankdir=TB
labelloc=t; label="MGW Endpoint FSM"
gscon_ensure_mgw_endpoint [label="gscon_ensure_mgw_endpoint()",shape="box"]
UNUSED
WAIT_MGW_RESPONSE
IN_USE
terminate [shape=octagon]
mgcp [label="mgcp client FSM\n(libosmo-mgcp-client)",shape=box3d]
notify [label="notify target FI",shape=box3d]
gscon [label="parent FI\n(gscon)",shape=box3d]
gscon_ensure_mgw_endpoint -> UNUSED
UNUSED -> WAIT_MGW_RESPONSE [label="first\nmgw_endpoint_ci_request(CRCX)"]
WAIT_MGW_RESPONSE -> mgcp [label="mgcp_conn_create()\nmgcp_conn_modify()\nmgcp_conn_delete()",style=dotted]
mgcp -> WAIT_MGW_RESPONSE [label="CI[i] event",style=dotted]
WAIT_MGW_RESPONSE -> IN_USE
IN_USE -> notify [label="notify event for\nindividual CI request",style=dotted]
IN_USE -> WAIT_MGW_RESPONSE [label="additional\nmgw_endpoint_ci_request()\nCRCX,MDCX,DLCX"]
WAIT_MGW_RESPONSE -> terminate [label="all CI DLCX'd"]
terminate -> gscon [label="GSCON_EV_FORGET_MGW_ENDPOINT",style=dotted]
}

105
doc/mgw-endpoint.msc Normal file
View File

@ -0,0 +1,105 @@
msc {
hscale=2;
notify [label="calling FSM"], mgwep[label="MGW endpoint FSM"], mgcp[label="mgcp client FSM"],
mgw[label="MGW"];
notify note mgw [label="MGW endpoint FSM\nmanages multiple CI for one endpoint"];
|||;
notify rbox notify [label="conn FSM"];
notify box notify [label="gscon_ensure_mgw_endpoint()"];
notify -> mgwep [label="mgw_endpoint_alloc()"];
mgwep abox mgwep [label="MGWEP_ST_UNUSED"];
...;
...;
...;
notify rbox mgw [label="CRCX"];
notify rbox notify [label="lchan RTP FSM"];
notify -> mgwep [label="mgw_endpoint_ci_add()"];
mgwep note mgwep [label="Return an unassigned endpoint CI slot in the local array"];
...;
mgwep note mgwep [label="First request on a CI must be a CRCX"];
notify -> mgwep [label="mgw_endpoint_ci_request(CRCX)"];
notify note mgwep [label="verb=CRCX\nverb_info='rtpbridge/*@mgw'\nnotify_event"];
mgwep box mgwep [label="CI[x].pending=true"];
mgwep abox mgwep [label="MGWEP_ST_WAIT_MGW_RESPONSE"];
|||;
notify note mgwep [label="If more mgw_endpoint_ci_request() are triggered, they will be set to
'pending' and wait until all ongoing requests are through and MGWEP_ST_IN_USE is
reached."];
|||;
mgwep box mgwep [label="for each pending CI:\nsend_verb()"];
mgwep -> mgcp [label="CI[x]: mgcp_conn_create()"];
mgwep note mgcp [label="Each CI[i] has two events from the FSM instance event range assigned, one
for success, one for failure. These are passed to the mgcp client FSM."];
mgcp => mgw [label="CRCX"];
...;
mgcp <= mgw [label="CRCX OK"];
mgcp note mgw [label="MGW returns:\n'rtpbridge/123@mgw',\nnew CI identifier '123abc',\n
MGW side RTP IP:port"];
mgwep <- mgcp [label="CI[x] success event"];
mgwep box mgwep [label="on_success(CI[x])"];
mgwep note mgwep [label="CI[x].rtp_info = IP:port\nmgcp_ci_str = '123abc'\n
endpoint name = 'rtpbridge/123@mgw'"];
notify <- mgwep [label="notify_event from mgw_endpoint_ci_request()"];
notify note mgwep [label="notify_event will be one of:\n
LCHAN_RTP_EV_MGW_ENDPOINT_AVAILABLE (towards BTS)\n
ASSIGNMENT_EV_MSC_MGW_OK (towards MSC)\n
HO_EV_MSC_MGW_OK (towards MSC)"];
mgwep abox mgwep [label="MGWEP_ST_IN_USE"];
...;
...;
...;
notify rbox mgw [label="MDCX"];
mgwep note mgwep [label="Second or later request on a CI must be MDCX or DLCX"];
notify -> mgwep [label="mgw_endpoint_ci_request(MDCX)"];
notify note mgwep [label="verb=MDCX\nverb_info=BTS RTP IP:port\n
automatic: full endpoint name as from CRCX OK\n
notify_event\n"];
mgwep box mgwep [label="CI[x].pending=true"];
mgwep abox mgwep [label="MGWEP_ST_WAIT_MGW_RESPONSE"];
mgwep box mgwep [label="for each pending CI:\nsend_verb()"];
mgwep -> mgcp [label="CI[x]: mgcp_conn_modify()"];
mgcp => mgw [label="MDCX"];
...;
mgcp <= mgw [label="MDCX OK"];
mgwep <- mgcp [label="CI[x] success event"];
mgwep box mgwep [label="on_success(CI[x])"];
notify <- mgwep [label="notify_event from mgw_endpoint_ci_request()"];
notify note mgwep [label="notify_event will be one of:\n
LCHAN_RTP_EV_MGW_ENDPOINT_CONFIGURED (towards BTS)\n
ASSIGNMENT_EV_MSC_MGW_OK (towards MSC)\n
HO_EV_MSC_MGW_OK (towards MSC)"];
mgwep abox mgwep [label="MGWEP_ST_IN_USE"];
...;
...;
...;
notify rbox mgw [label="DLCX"];
notify -> mgwep [label="mgw_endpoint_ci_dlcx()"];
mgwep box mgwep [label="mgw_endpoint_ci_request(DLCX)"];
mgwep box mgwep [label="CI[x].pending=true"];
mgwep abox mgwep [label="MGWEP_ST_WAIT_MGW_RESPONSE"];
mgwep box mgwep [label="for each pending CI:\nsend_verb()"];
mgwep -> mgcp [label="CI[x]: mgcp_conn_delete()"];
mgcp => mgw [label="DLCX"];
mgcp box mgcp [label="detach from parent fi"];
mgwep box mgwep [label="forget and clear CI[x]"];
--- [label="IF other CI remain valid"];
mgwep abox mgwep [label="MGWEP_ST_IN_USE"];
--- [label="IF no CI remain on endpoint"];
mgwep abox mgwep [label="terminate"];
notify rbox notify [label="conn FSM"];
notify <- mgwep [label="GSCON_EV_FORGET_MGW_ENDPOINT"];
---;
...;
mgcp <= mgw [label="DLCX OK"];
mgcp abox mgcp [label="terminate"];
}

View File

@ -1,59 +0,0 @@
msc {
hscale=2;
ms [label="MS"], bts [label="BTS"], bsc[label="BSC"], bsc_lchan[label="BSC lchan FSM"];
ms note bsc_lchan [label="lchan allocation sequence for RSL Channel Request"];
ms => bts [label="RR Channel Request"];
bts => bsc [label="RSL Channel Request"];
bsc box bsc [label="rsl_rx_chan_rqd()"];
bsc note bsc [label="Obtain RACH data from Request: - Reference - Access Delay (TA)
- Request Reason - Channel Type"];
bsc note bsc [label="If the reason is PDCH, the RACH Request is forwarded to PCU and BSC is no
longer concerned (rsl_rx_pchan_rqd())."];
bsc note bsc [label="Always try to allocate an SDCCH regardless of the requested type, only if no
SDCCH is available, look for the actually requested channel type."];
bsc box bsc [label="lchan_select_by_type(SDCCH)"];
--- [label="IF no lchan is available (neither SDCCH nor requested type)"];
bsc note bsc [label="Figure out T3122 value from bts->T3122, network->T3122 or
GSM_T3122_DEFAULT"];
bsc box bsc [label="rsl_send_imm_ass_rej(wait_ind=T3122)"];
bsc note bsc [label="..."];
bts <= bsc [label="RR Immediate Assign Reject"];
ms <= bts [label="RR Immediate Assign Reject (possibly grouped with up to 4 others)"];
bsc note bsc [label="rsl_rx_pchan_rqd() exits, no channel is allocated."];
--- [label="END: no lchan is available"];
bsc box bsc [label="Store RACH data in lchan->rqd_ref, rqd_ta"];
bsc -> bsc_lchan [label="lchan_allocate(FOR_MS_CHANNEL_REQUEST)"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_ACTIV_ACK\nT3103"];
bsc_lchan note bsc_lchan [label="The lchan FSM knows that FOR_MS_CHANNEL_REQUEST is about
Immediate Assignment."];
bts <= bsc_lchan [label="RSL Chan Activ (Immediate Assignment)"];
...;
--- [label="on any error"];
bts <= bsc_lchan [label="RR Immediate Assign Reject"];
ms <= bts [label="RR Immediate Assign Reject (possibly grouped with up to 4 others)"];
---;
...;
bts => bsc_lchan [label="RSL Chan Activ ACK"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_\nRLL_ESTABLISH\ncontinue T3103"];
...;
--- [label="on timeout"];
bsc_lchan box bsc_lchan [label="lchan_error_release(deact_sacch=true)"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_RF_RELEASE_ACK"];
bts <= bsc_lchan [label="RLL Release Request (Local End)..."];
bts <= bsc_lchan [label="...for all SAPIs including [0]"];
bts <= bsc_lchan [label="RSL Deactivate SACCH"];
bts <= bsc_lchan [label="RSL RF Channel Release"];
...;
bts => bsc_lchan [label="RSL RF Channel Release ACK"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_WAIT_AFTER_ERROR"];
...;
bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];
---;
ms => bsc_lchan [label="RLL Establish Ind"];
bsc_lchan box bsc_lchan [label="associate lchan FSM with new conn FSM"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];
}

View File

@ -1,10 +1,11 @@
digraph G {
rankdir=TB;
rankdir=TB
labelloc=t; label="Timeslot FSM"
invisible [style="invisible"]
invisible2 [style="invisible"]
NOT_INITIALIZED
lchan [label="lchan FSM",shape=box3d];
lchan [label="lchan FSM",shape=box3d]
UNUSED
IN_USE
BORKEN

View File

@ -1,25 +1,24 @@
msc {
hscale=2;
bts [label="MS/BTS"], bsc[label="BSC"], bsc_ts[label="BSC timeslot FSM"], bsc_lchan[label="BSC lchan FSM"];
bsc_ts abox bsc_ts [label="NOT_INITIALIZED (no timeout)"];
bsc_ts abox bsc_ts [label="NOT_INITIALIZED"];
...;
bsc note bsc_ts [label="OML and RSL may be established in any order"];
bts => bsc_ts [label="OML: Channel OPSTART ACK"];
bsc -> bsc_ts [label="RSL bootstrapped"];
bsc_ts abox bsc_ts [label="UNUSED (no timeout)"];
bsc_ts abox bsc_ts [label="UNUSED"];
|||;
bts rbox bsc_lchan [label="UNUSED, onenter"];
bsc_ts abox bsc_ts [label="UNUSED"];
--- [label="GPRS enabled?"];
--- [label="IF: dedicated PDCH?"];
bsc_ts abox bsc_ts [label="PDCH (no timeout)"];
bsc_ts abox bsc_ts [label="PDCH"];
|||;
--- [label="IF: dynamic timeslot"];
bsc_ts abox bsc_ts [label="WAIT_PDCH_ACT (?s, Tnnnn)"];
bsc_ts abox bsc_ts [label="WAIT_PDCH_ACT (4s, T23001)"];
bts <= bsc_ts [label="RSL Chan Activ of PDCH",ID="Osmocom style"];
bts <= bsc_ts [label="RSL PDCH Act",ID="ip.access style"];
...;
@ -29,7 +28,7 @@ msc {
...;
bts => bsc_ts [label="RSL RF Chan Activ ACK",ID="Osmocom style"];
bts => bsc_ts [label="RSL PDCH Act ACK",ID="ip.access style"];
bsc_ts abox bsc_ts [label="PDCH (no timeout)"];
bsc_ts abox bsc_ts [label="PDCH"];
--- [label="END: GPRS enabled?"];
...;
@ -43,12 +42,14 @@ msc {
bts <= bsc_lchan [label="RSL Chan Activ (and so on)"];
...;
bts rbox bsc_lchan [label="IN_USE, second lchan"];
bsc_ts abox bsc_ts [label="IN_USE"];
bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_REQUESTED (data=lchan)"];
bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_READY"];
bts <= bsc_lchan [label="RSL Chan Activ (and so on)"];
...;
...;
bts rbox bsc_lchan [label="IN_USE, when lchan FSM releases (both regularly, or due to error)"];
bsc_ts abox bsc_ts [label="IN_USE"];
bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED (data=lchan)"];
--- [label="IF all lchan->fi->state == LCHAN_ST_UNUSED"];
bsc_ts abox bsc_ts [label="UNUSED"];
@ -57,13 +58,14 @@ msc {
...;
bts rbox bsc_lchan [label="PDCH on lchan request"];
bts rbox bsc_lchan [label="PDCH, on lchan request"];
bsc_ts note bsc_lchan [label="TS_EV_LCHAN_REQUESTED should only come in on
lchans where it makes sense, both from TS kind as well as not
conflicting with other users of the lchan."];
bsc_ts abox bsc_ts [label="PDCH"];
bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_REQUESTED"];
bsc_ts abox bsc_ts [label="WAIT_PDCH_DEACT (?s, Tnnnn)"];
bsc_ts abox bsc_ts [label="WAIT_PDCH_DEACT (4s, T23001)"];
bts <= bsc_ts [label="RSL RF Chan Release of PDCH",ID="Osmocom style"];
bts <= bsc_ts [label="RSL PDCH Deact",ID="ip.access style"];
...;

View File

@ -55,7 +55,7 @@ msc {
--- [label="dyn TS"];
bsc_ts box bsc_ts [label="onenter of TS_ST_UNUSED:"];
bsc_ts abox bsc_ts [label="TS_ST_WAIT_PDCH_ACT"];
...;
... [label="..."];
bsc_ts abox bsc_ts [label="PDCH"];
--- [label="END: dyn TS"];
--- [label="END: OML and RSL ready"];
@ -65,13 +65,13 @@ msc {
bsc_lchan -> bsc_ts [label="TS_EV_LCHAN_REQUESTED"];
--- [label="dyn TS"];
bsc_ts note bsc_ts [label="possibly switch from PDCH...\n(see timeslot FSM)"];
bsc_ts rbox bsc_ts [label="possibly switch from PDCH...\n(see timeslot FSM)"];
bsc_ts box bsc_ts [label="ts->pchan =\n requested GSM_PCHAN_XXX type"];
---;
bsc_ts -> bsc_lchan [label="LCHAN_EV_TS_READY"];
bsc_lchan note bsc_lchan [label="RSL Chan Alloc and so fort..."];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_ACTIVE"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_ESTABLISHED"];
...;
bsc -> bsc_lchan [label="LCHAN_EV_RELEASE"];
bsc_lchan note bsc_lchan [label="...RSL RF Chan Release..."];
@ -79,7 +79,7 @@ msc {
bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED"];
bsc_ts abox bsc_ts [label="TS_ST_UNUSED"];
--- [label="dyn TS"];
bsc_ts note bsc_ts [label="possibly switch to PDCH"];
bsc_ts rbox bsc_ts [label="possibly switch to PDCH"];
---;
...;
...;
@ -88,8 +88,8 @@ msc {
bsc -> bsc_ts [label="ts[*]:"];
bsc_ts abox bsc_ts [label="TS_ST_NOT_INITIALIZED"];
bsc_ts note bsc_lchan [label="If it's just the RSL being dropped, transition lchan FSMs to
LCHAN_ST_UNUSED, but keep them allocated. Unless OML is re-established, any vty pchan
modifications must not take effect."];
LCHAN_ST_UNUSED, but keep them allocated. Unless OML is re-established, any telnet
vty pchan modifications must not take effect."];
bsc_ts -> bsc_lchan [label="lchan[*]:"];
bsc_lchan abox bsc_lchan [label="LCHAN_ST_UNUSED"];
bsc_ts <- bsc_lchan [label="TS_EV_LCHAN_UNUSED (ignored)"];