neels has submitted this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/31028 )
Change subject: fix SCCP conn leak on non-graceful HNB shutdown ......................................................................
fix SCCP conn leak on non-graceful HNB shutdown
Clean up SCCP connections when a HNB disconnects.
When a HNB disconnects, we clean up all RUA <-> SCCP connection state for that HNB. In that cleanup, discarding the SCCP connection is so far missing.
Add a flag indicating true between SCCP CC and DISCONNECT. Hence we can tell during context_map_deactivate() whether the cleanup is graceful (DISCONNECT already sent) or non-graceful (need to DISCONNECT).
Change-Id: Icc2db9f6c0b2d0a814ff1110ffbe5e8f7f629222 --- M include/osmocom/hnbgw/context_map.h M src/osmo-hnbgw/context_map.c M src/osmo-hnbgw/hnbgw_cn.c M src/osmo-hnbgw/hnbgw_rua.c 4 files changed, 26 insertions(+), 1 deletion(-)
Approvals: Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved
diff --git a/include/osmocom/hnbgw/context_map.h b/include/osmocom/hnbgw/context_map.h index 99efe8a..fe09da0 100644 --- a/include/osmocom/hnbgw/context_map.h +++ b/include/osmocom/hnbgw/context_map.h @@ -43,6 +43,10 @@ bool is_ps; /* SCCP User SAP connection ID */ uint32_t scu_conn_id; + /* Set to true on SCCP Conn Conf, set to false when an OSMO_SCU_PRIM_N_DISCONNECT has been sent for the SCCP + * User SAP conn. Useful to avoid leaking SCCP connections: guarantee that an OSMO_SCU_PRIM_N_DISCONNECT gets + * sent, even when RUA fails to gracefully disconnect. */ + bool scu_conn_active; /* Pending data to be sent: when we send an "empty" SCCP CR first, the initial RANAP message will be sent in a * separate DT once the CR is confirmed. This caches the initial RANAP message. */ struct msgb *cached_msg; diff --git a/src/osmo-hnbgw/context_map.c b/src/osmo-hnbgw/context_map.c index 98dffad..31ba032 100644 --- a/src/osmo-hnbgw/context_map.c +++ b/src/osmo-hnbgw/context_map.c @@ -26,6 +26,8 @@
#include <osmocom/core/timer.h>
+#include <osmocom/sigtran/sccp_helpers.h> + #include <osmocom/hnbgw/hnbgw.h> #include <osmocom/hnbgw/hnbgw_rua.h> #include <osmocom/hnbgw/context_map.h> @@ -174,6 +176,12 @@ if (map->state != MAP_S_RESERVED2) map->state = MAP_S_RESERVED1;
+ /* Is SCCP still active and needs to be disconnected ungracefully? */ + if (map->scu_conn_active) { + osmo_sccp_tx_disconn(map->hnb_ctx->gw->sccp.cnlink->sccp_user, map->scu_conn_id, NULL, 0); + map->scu_conn_active = false; + } + /* a possibly still existing MGW FSM must be terminated when the context * map is deactivated. (this is a cornercase) */ if (map->mgw_fi) { diff --git a/src/osmo-hnbgw/hnbgw_cn.c b/src/osmo-hnbgw/hnbgw_cn.c index 7cbfcec..c4189e8 100644 --- a/src/osmo-hnbgw/hnbgw_cn.c +++ b/src/osmo-hnbgw/hnbgw_cn.c @@ -337,6 +337,8 @@ struct osmo_prim_hdr *oph) { struct osmo_ss7_instance *ss7 = osmo_sccp_get_ss7(cnlink->gw->sccp.client); + struct hnbgw_context_map *map; + LOGP(DMAIN, LOGL_DEBUG, "handle_cn_conn_conf() conn_id=%d, addrs: called=%s calling=%s responding=%s\n", param->conn_id, osmo_sccp_addr_to_str_c(OTC_SELECT, ss7, ¶m->called_addr), @@ -346,9 +348,17 @@ /* Nothing needs to happen for RUA, RUA towards the HNB doesn't seem to know any confirmations to its CONNECT * operation. */
+ map = context_map_by_cn(cnlink, param->conn_id); + if (!map) + return 0; + + /* SCCP connection is confirmed. Mark conn as active, i.e. requires a DISCONNECT to clean up the SCCP + * connection. */ + map->scu_conn_active = true; + /* If our initial SCCP CR was sent without data payload, then the initial RANAP message is cached and waiting to * be sent as soon as the SCCP connection is confirmed. See if that is the case, send cached data. */ - context_map_send_cached_msg(context_map_by_cn(cnlink, param->conn_id)); + context_map_send_cached_msg(map);
return 0; } diff --git a/src/osmo-hnbgw/hnbgw_rua.c b/src/osmo-hnbgw/hnbgw_rua.c index f4e24d7..215379a 100644 --- a/src/osmo-hnbgw/hnbgw_rua.c +++ b/src/osmo-hnbgw/hnbgw_rua.c @@ -252,6 +252,9 @@ prim->u.disconnect.conn_id = map->scu_conn_id; prim->u.disconnect.cause = cause; release_context_map = true; + /* Mark SCCP conn as gracefully disconnected */ + if (map) + map->scu_conn_active = false; break; case OSMO_SCU_PRIM_N_UNITDATA: prim->u.unitdata.called_addr = *remote_addr;