neels has submitted this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/32915 )
Change subject: immediately SCCP RLSD on HNB re-register ......................................................................
immediately SCCP RLSD on HNB re-register
The RUA side may disconnect a) gracefully (RUA Disconnect with RANAP IU Release Complete) or b) by detecting that the HNB is gone / has restarted
For a), the SCCP side waits for a RLSD from the CN that follows the IU Release Complete. For b), we so far also wait for a RLSD from CN, which will never come, and only after a timeout send an SCCP RLSD to the CN.
Instead, for b), immediately send an SCCP RLSD.
To distinguish between the graceful release (a) and the disruptive release (b), add new state MAP_RUA_ST_DISRUPTED on the RUA side, and add new event MAP_SCCP_EV_RAN_LINK_LOST for the SCCP side.
Any non-graceful disconnect of RUA enters ST_DISRUPTED. disrupted_onenter() dispatches EV_RAN_LINK_LOST to SCCP, and SCCP directly sends RLSD to the CN without timeout.
These changes are also shown in doc/charts/hnbgw_context_map.msc.
Change-Id: I4e78617ad39bb73fe92097c8a1a8069da6a7f6a1 --- M doc/charts/hnbgw_context_map.msc M include/osmocom/hnbgw/context_map.h M src/osmo-hnbgw/context_map_rua.c M src/osmo-hnbgw/context_map_sccp.c 4 files changed, 95 insertions(+), 15 deletions(-)
Approvals: pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve neels: Looks good to me, approved
diff --git a/doc/charts/hnbgw_context_map.msc b/doc/charts/hnbgw_context_map.msc index 7a4da55..d287d89 100644 --- a/doc/charts/hnbgw_context_map.msc +++ b/doc/charts/hnbgw_context_map.msc @@ -65,7 +65,7 @@ sccp abox sccp [label="MAP_SCCP_ST_DISCONNECTED"]; rua <= sccp [label="MAP_RUA_EV_CN_DISC"]; hnb <= rua [label="RUA Disconnect"]; - rua abox rua [label="MAP_RUA_ST_DISCONNECTED"]; + rua abox rua [label="MAP_RUA_ST_DISRUPTED"]; rua rbox sccp [label="map_check_released()"]; rua rbox sccp [label="hnbgw_context_map_free()"];
@@ -81,10 +81,10 @@ --- [label="Ungraceful release from HNB"]; hnb -x rua [label="link loss"]; rua rbox rua [label="MAP_RUA_EV_HNB_LINK_LOST"]; - rua => sccp [label="MAP_SCCP_EV_RAN_DISC"]; + rua abox rua [label="MAP_RUA_ST_DISRUPTED"]; + rua => sccp [label="MAP_SCCP_EV_RAN_LINK_LOST"]; sccp => cn [label="SCCP Released"]; sccp abox sccp [label="MAP_SCCP_ST_DISCONNECTED"]; - rua abox rua [label="MAP_RUA_ST_DISCONNECTED"]; rua rbox sccp [label="map_check_released()"]; rua rbox sccp [label="hnbgw_context_map_free()"];
@@ -98,10 +98,8 @@ rua rbox rua [label="MAP_RUA_EV_HNB_LINK_LOST"]; hnb <= rua [label="RUA Disconnect"]; hnb note rua [label="TODO: does it make sense to send\nRUA Disconnect per context when HNB is/was gone?\nOr has the HNB implicitly discarded these?"]; - rua abox rua [label="MAP_RUA_ST_DISCONNECTED"]; - rua => sccp [label="MAP_SCCP_EV_RAN_DISC\nfrom map_rua_disconnected_onenter()"]; - sccp abox sccp [label="MAP_SCCP_ST_WAIT_RLSD"]; - rua => sccp [label="MAP_SCCP_EV_RAN_DISC\nto skip waiting for SCCP Released from CN"]; + rua abox rua [label="MAP_RUA_ST_DISRUPTED"]; + rua => sccp [label="MAP_SCCP_EV_RAN_LINK_LOST\nfrom map_rua_disrupted_onenter()"]; sccp => cn [label="SCCP Released"]; sccp abox sccp [label="MAP_SCCP_ST_DISCONNECTED"]; rua rbox sccp [label="map_check_released()"]; diff --git a/include/osmocom/hnbgw/context_map.h b/include/osmocom/hnbgw/context_map.h index a2e76c3..9320ce0 100644 --- a/include/osmocom/hnbgw/context_map.h +++ b/include/osmocom/hnbgw/context_map.h @@ -51,6 +51,8 @@ * CN should have received an Iu-ReleaseComplete with or before this, give CN a chance to send an SCCP RLSD; * after a timeout we will send a non-standard RLSD to the CN instead. */ MAP_SCCP_EV_RAN_DISC, + /* The RAN released ungracefully. We will directly disconnect the SCCP connection, too. */ + MAP_SCCP_EV_RAN_LINK_LOST, /* Receiving an SCCP RLSD from CN, or libosmo-sigtran tells us about SCCP connection timeout. All done. */ MAP_SCCP_EV_RX_RELEASED, }; diff --git a/src/osmo-hnbgw/context_map_rua.c b/src/osmo-hnbgw/context_map_rua.c index f50f711..9e8f028 100644 --- a/src/osmo-hnbgw/context_map_rua.c +++ b/src/osmo-hnbgw/context_map_rua.c @@ -41,6 +41,7 @@ MAP_RUA_ST_INIT, MAP_RUA_ST_CONNECTED, MAP_RUA_ST_DISCONNECTED, + MAP_RUA_ST_DISRUPTED, };
static const struct value_string map_rua_fsm_event_names[] = { @@ -58,6 +59,7 @@ static const struct osmo_tdef_state_timeout map_rua_fsm_timeouts[32] = { [MAP_RUA_ST_INIT] = { .T = -31 }, [MAP_RUA_ST_DISCONNECTED] = { .T = -31 }, + [MAP_RUA_ST_DISRUPTED] = { .T = -31 }, };
/* Transition to a state, using the T timer defined in map_rua_fsm_timeouts. @@ -93,6 +95,7 @@ return MAP_S_ACTIVE; default: case MAP_RUA_ST_DISCONNECTED: + case MAP_RUA_ST_DISRUPTED: return MAP_S_DISCONNECTING; } } @@ -103,6 +106,7 @@ return false; switch (map->rua_fi->state) { case MAP_RUA_ST_DISCONNECTED: + case MAP_RUA_ST_DISRUPTED: return false; default: return true; @@ -114,10 +118,11 @@ /* Return 1 to terminate FSM instance, 0 to keep running */ switch (fi->state) { default: - map_rua_fsm_state_chg(MAP_RUA_ST_DISCONNECTED); + map_rua_fsm_state_chg(MAP_RUA_ST_DISRUPTED); return 0;
case MAP_RUA_ST_DISCONNECTED: + case MAP_RUA_ST_DISRUPTED: return 1; } } @@ -210,8 +215,6 @@ return;
case MAP_RUA_EV_RX_DISCONNECT: - case MAP_RUA_EV_CN_DISC: - case MAP_RUA_EV_HNB_LINK_LOST: /* Unlikely that SCCP is active, but let the SCCP FSM decide about that. */ handle_rx_rua(fi, ranap_msg); /* There is a reason to shut down this RUA connection. Super unlikely, we haven't even processed the @@ -220,6 +223,11 @@ map_rua_fsm_state_chg(MAP_RUA_ST_DISCONNECTED); break;
+ case MAP_RUA_EV_CN_DISC: + case MAP_RUA_EV_HNB_LINK_LOST: + map_rua_fsm_state_chg(MAP_RUA_ST_DISRUPTED); + break; + default: OSMO_ASSERT(false); } @@ -276,14 +284,14 @@
case MAP_RUA_EV_HNB_LINK_LOST: /* The HNB is gone. Cannot gracefully cleanup the RUA connection, just be gone. */ - map_rua_fsm_state_chg(MAP_RUA_ST_DISCONNECTED); + map_rua_fsm_state_chg(MAP_RUA_ST_DISRUPTED); return;
case MAP_RUA_EV_CN_DISC: /* There is a disruptive reason to shut down this RUA connection, HNB is still there */ OSMO_ASSERT(data == NULL); map_rua_tx_disconnect(fi); - map_rua_fsm_state_chg(MAP_RUA_ST_DISCONNECTED); + map_rua_fsm_state_chg(MAP_RUA_ST_DISRUPTED); return;
default: @@ -291,23 +299,35 @@ } }
-static void map_rua_disconnected_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +static void map_rua_free_if_done(struct hnbgw_context_map *map, uint32_t sccp_event) { - struct hnbgw_context_map *map = fi->priv; /* From RUA's POV, we can now free the hnbgw_context_map. * If SCCP is still active, tell it to disconnect -- in that case the SCCP side will call context_map_free(). * If SCCP is no longer active, free this map. */ if (map_sccp_is_active(map)) - map_sccp_dispatch(map, MAP_SCCP_EV_RAN_DISC, NULL); + map_sccp_dispatch(map, sccp_event, NULL); else context_map_free(map); }
+static void map_rua_disconnected_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct hnbgw_context_map *map = fi->priv; + map_rua_free_if_done(map, MAP_SCCP_EV_RAN_DISC); +} + static void map_rua_disconnected_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct msgb *ranap_msg = data; if (msg_has_l2_data(ranap_msg)) LOGPFSML(fi, LOGL_ERROR, "RUA not connected, cannot dispatch RANAP message\n"); + /* Ignore all events. */ +} + +static void map_rua_disrupted_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct hnbgw_context_map *map = fi->priv; + map_rua_free_if_done(map, MAP_SCCP_EV_RAN_LINK_LOST); }
void map_rua_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause) @@ -331,6 +351,7 @@ | S(MAP_RUA_ST_INIT) | S(MAP_RUA_ST_CONNECTED) | S(MAP_RUA_ST_DISCONNECTED) + | S(MAP_RUA_ST_DISRUPTED) , .action = map_rua_init_action, }, @@ -345,6 +366,7 @@ , .out_state_mask = 0 | S(MAP_RUA_ST_DISCONNECTED) + | S(MAP_RUA_ST_DISRUPTED) , .action = map_rua_connected_action, }, @@ -357,6 +379,16 @@ .onenter = map_rua_disconnected_onenter, .action = map_rua_disconnected_action, }, + [MAP_RUA_ST_DISRUPTED] = { + .name = "disrupted", + .in_event_mask = 0 + | S(MAP_RUA_EV_CN_DISC) + | S(MAP_RUA_EV_HNB_LINK_LOST) + , + .onenter = map_rua_disrupted_onenter, + /* same as MAP_RUA_ST_DISCONNECTED: */ + .action = map_rua_disconnected_action, + }, };
static struct osmo_fsm map_rua_fsm = { diff --git a/src/osmo-hnbgw/context_map_sccp.c b/src/osmo-hnbgw/context_map_sccp.c index 132d03e..3de8215 100644 --- a/src/osmo-hnbgw/context_map_sccp.c +++ b/src/osmo-hnbgw/context_map_sccp.c @@ -52,6 +52,7 @@ OSMO_VALUE_STRING(MAP_SCCP_EV_RX_DATA_INDICATION), OSMO_VALUE_STRING(MAP_SCCP_EV_TX_DATA_REQUEST), OSMO_VALUE_STRING(MAP_SCCP_EV_RAN_DISC), + OSMO_VALUE_STRING(MAP_SCCP_EV_RAN_LINK_LOST), OSMO_VALUE_STRING(MAP_SCCP_EV_RX_RELEASED), {} }; @@ -262,6 +263,7 @@ map_sccp_fsm_state_chg(MAP_SCCP_ST_WAIT_CC); return;
+ case MAP_SCCP_EV_RAN_LINK_LOST: case MAP_SCCP_EV_RAN_DISC: /* No CR has been sent yet, just go to disconnected state. */ if (msg_has_l2_data(ranap_msg)) @@ -297,6 +299,7 @@ LOGPFSML(fi, LOGL_ERROR, "Connection not yet confirmed, cannot forward RANAP to CN\n"); return;
+ case MAP_SCCP_EV_RAN_LINK_LOST: case MAP_SCCP_EV_RAN_DISC: /* RUA connection was terminated. First wait for the CC before releasing the SCCP conn. */ if (msg_has_l2_data(ranap_msg)) @@ -351,6 +354,16 @@ tx_sccp_df1(fi, ranap_msg); return;
+ case MAP_SCCP_EV_RAN_LINK_LOST: + /* RUA has disconnected ungracefully, so there is no Iu Release that told the CN to disconnect. + * Disconnect on the SCCP layer, ungracefully. */ + /* There won't be any ranap_msg, but if a caller wants to dispatch a msg, forward it before + * disconnecting. */ + tx_sccp_df1(fi, ranap_msg); + tx_sccp_rlsd(fi); + map_sccp_fsm_state_chg(MAP_SCCP_ST_DISCONNECTED); + return; + case MAP_SCCP_EV_RX_RELEASED: /* The CN sends an N-Disconnect (SCCP Released) out of the usual sequence. Not what we expected, but * handle it. */ @@ -480,6 +493,7 @@ .in_event_mask = 0 | S(MAP_SCCP_EV_TX_DATA_REQUEST) | S(MAP_SCCP_EV_RAN_DISC) + | S(MAP_SCCP_EV_RAN_LINK_LOST) | S(MAP_SCCP_EV_RX_RELEASED) , .out_state_mask = 0 @@ -495,6 +509,7 @@ | S(MAP_SCCP_EV_RX_CONNECTION_CONFIRM) | S(MAP_SCCP_EV_TX_DATA_REQUEST) | S(MAP_SCCP_EV_RAN_DISC) + | S(MAP_SCCP_EV_RAN_LINK_LOST) | S(MAP_SCCP_EV_RX_RELEASED) , .out_state_mask = 0 @@ -509,6 +524,7 @@ | S(MAP_SCCP_EV_RX_DATA_INDICATION) | S(MAP_SCCP_EV_TX_DATA_REQUEST) | S(MAP_SCCP_EV_RAN_DISC) + | S(MAP_SCCP_EV_RAN_LINK_LOST) | S(MAP_SCCP_EV_RX_RELEASED) | S(MAP_SCCP_EV_RX_CONNECTION_CONFIRM) , @@ -526,6 +542,7 @@ | S(MAP_SCCP_EV_RX_DATA_INDICATION) | S(MAP_SCCP_EV_TX_DATA_REQUEST) | S(MAP_SCCP_EV_RAN_DISC) + | S(MAP_SCCP_EV_RAN_LINK_LOST) | S(MAP_SCCP_EV_RX_CONNECTION_CONFIRM) , .out_state_mask = 0 @@ -539,6 +556,7 @@ .in_event_mask = 0 | S(MAP_SCCP_EV_TX_DATA_REQUEST) | S(MAP_SCCP_EV_RAN_DISC) + | S(MAP_SCCP_EV_RAN_LINK_LOST) , .onenter = map_sccp_disconnected_onenter, .action = map_sccp_disconnected_action,