pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/40246?usp=email )
Change subject: Fix lifecycle of struct hnbgw_sccp_user ...................................................................... Fix lifecycle of struct hnbgw_sccp_user There's one struct hnbgw_sccp_user per cs7 instance configured in the hnbgw process. Multiple cnlinks configured on the same cs7 instance will be referencing/using the same struct hnbgw_sccp_user pointer. Hence, it makes no sense to allocate the struct using a talloc context of a cnlink as a parent, nor to keep any kind of specific 1-1 reference to it. Instead, we need to keep it alive in a ref-count basis, and unbind it from libosmo-sigtran sccp SAP and destroy it once no more cnlinks use it. Change-Id: I524f6da8e5936135b2153def103d83cec6549f94 --- M include/osmocom/hnbgw/hnbgw_cn.h M include/osmocom/hnbgw/hnbgw_sccp.h M src/osmo-hnbgw/cnlink.c M src/osmo-hnbgw/hnbgw_cn.c M src/osmo-hnbgw/hnbgw_sccp.c 5 files changed, 110 insertions(+), 42 deletions(-) Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved laforge: Looks good to me, but someone else must approve osmith: Looks good to me, but someone else must approve diff --git a/include/osmocom/hnbgw/hnbgw_cn.h b/include/osmocom/hnbgw/hnbgw_cn.h index 78b82b7..8f7919f 100644 --- a/include/osmocom/hnbgw/hnbgw_cn.h +++ b/include/osmocom/hnbgw/hnbgw_cn.h @@ -14,6 +14,7 @@ void hnbgw_cnpool_apply_cfg(struct hnbgw_cnpool *cnpool); void hnbgw_cnpool_cnlinks_start_or_restart(struct hnbgw_cnpool *cnpool); int hnbgw_cnlink_start_or_restart(struct hnbgw_cnlink *cnlink); +void hnbgw_cnlink_drop_sccp(struct hnbgw_cnlink *cnlink); char *cnlink_sccp_addr_to_str(struct hnbgw_cnlink *cnlink, const struct osmo_sccp_addr *addr); diff --git a/include/osmocom/hnbgw/hnbgw_sccp.h b/include/osmocom/hnbgw/hnbgw_sccp.h index 7cf67a5..fbb84f4 100644 --- a/include/osmocom/hnbgw/hnbgw_sccp.h +++ b/include/osmocom/hnbgw/hnbgw_sccp.h @@ -4,6 +4,7 @@ #include <osmocom/core/hashtable.h> #include <osmocom/core/linuxlist.h> #include <osmocom/core/prim.h> +#include <osmocom/core/use_count.h> #include <osmocom/sigtran/sccp_sap.h> @@ -27,6 +28,9 @@ /* osmo_sccp API state for above local address on above ss7 instance. */ struct osmo_sccp_user *sccp_user; + /* Ref count of users of this struct, ie.referencing it in cnlink->hnbgw_sccp_user */ + struct osmo_use_count use_count; + /* Fast access to the hnbgw_context_map responsible for a given SCCP conn_id of the ss7->sccp instance. * hlist_node: hnbgw_context_map->hnbgw_sccp_user_entry. */ DECLARE_HASHTABLE(hnbgw_context_map_by_conn_id, 6); @@ -35,4 +39,10 @@ #define LOG_HSU(HSU, SUBSYS, LEVEL, FMT, ARGS...) \ LOGP(SUBSYS, LEVEL, "(%s) " FMT, (HSU) ? (HSU)->name : "null", ##ARGS) -struct hnbgw_sccp_user *hnbgw_sccp_user_alloc(const struct hnbgw_cnlink *cnlink, int ss7_inst_id); +#define HSU_USE_CNLINK "cnlink" +#define hnbgw_sccp_user_get(hsu, use) \ + OSMO_ASSERT(osmo_use_count_get_put(&(hsu)->use_count, use, 1) == 0) +#define hnbgw_sccp_user_put(hsu, use) \ + OSMO_ASSERT(osmo_use_count_get_put(&(hsu)->use_count, use, -1) == 0) + +struct hnbgw_sccp_user *hnbgw_sccp_user_alloc(int ss7_inst_id); diff --git a/src/osmo-hnbgw/cnlink.c b/src/osmo-hnbgw/cnlink.c index fc67fd3..137012a 100644 --- a/src/osmo-hnbgw/cnlink.c +++ b/src/osmo-hnbgw/cnlink.c @@ -98,11 +98,28 @@ return cnlink; } +void hnbgw_cnlink_drop_sccp(struct hnbgw_cnlink *cnlink) +{ + struct hnbgw_context_map *map, *map2; + struct hnbgw_sccp_user *hsu; + + llist_for_each_entry_safe(map, map2, &cnlink->map_list, hnbgw_cnlink_entry) { + map_sccp_dispatch(map, MAP_SCCP_EV_USER_ABORT, NULL); + } + + OSMO_ASSERT(cnlink->hnbgw_sccp_user); + hsu = cnlink->hnbgw_sccp_user; + cnlink->hnbgw_sccp_user = NULL; + hnbgw_sccp_user_put(hsu, HSU_USE_CNLINK); +} + void cnlink_term_and_free(struct hnbgw_cnlink *cnlink) { if (!cnlink) return; osmo_fsm_inst_term(cnlink->fi, OSMO_FSM_TERM_REQUEST, NULL); + if (cnlink->hnbgw_sccp_user) + hnbgw_cnlink_drop_sccp(cnlink); talloc_free(cnlink); } diff --git a/src/osmo-hnbgw/hnbgw_cn.c b/src/osmo-hnbgw/hnbgw_cn.c index 7b5c575..d0a11fd 100644 --- a/src/osmo-hnbgw/hnbgw_cn.c +++ b/src/osmo-hnbgw/hnbgw_cn.c @@ -134,17 +134,6 @@ return changed; } -static void hnbgw_cnlink_drop_sccp(struct hnbgw_cnlink *cnlink) -{ - struct hnbgw_context_map *map, *map2; - - llist_for_each_entry_safe(map, map2, &cnlink->map_list, hnbgw_cnlink_entry) { - map_sccp_dispatch(map, MAP_SCCP_EV_USER_ABORT, NULL); - } - - cnlink->hnbgw_sccp_user = NULL; -} - static void hnbgw_cnlink_log_self(struct hnbgw_cnlink *cnlink) { struct osmo_ss7_instance *ss7 = cnlink->hnbgw_sccp_user->ss7; @@ -210,9 +199,10 @@ llist_for_each_entry(hsu, &g_hnbgw->sccp.users, entry) { if (hsu->ss7 != ss7) continue; - cnlink->hnbgw_sccp_user = hsu; LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "using existing SCCP instance %s on cs7 instance %u\n", - hsu->name, osmo_ss7_instance_get_id(ss7)); + hsu->name, osmo_ss7_instance_get_id(ss7)); + cnlink->hnbgw_sccp_user = hsu; + hnbgw_sccp_user_get(cnlink->hnbgw_sccp_user, HSU_USE_CNLINK); hnbgw_cnlink_log_self(cnlink); return 0; } @@ -222,7 +212,8 @@ /* No SCCP instance yet for this ss7. Create it. If no address name is given that resolves to a * particular cs7 instance above, use 'cs7 instance 0'. */ - cnlink->hnbgw_sccp_user = hnbgw_sccp_user_alloc(cnlink, ss7 ? osmo_ss7_instance_get_id(ss7) : 0); + cnlink->hnbgw_sccp_user = hnbgw_sccp_user_alloc(ss7 ? osmo_ss7_instance_get_id(ss7) : 0); + hnbgw_sccp_user_get(cnlink->hnbgw_sccp_user, HSU_USE_CNLINK); hnbgw_cnlink_log_self(cnlink); return 0; } diff --git a/src/osmo-hnbgw/hnbgw_sccp.c b/src/osmo-hnbgw/hnbgw_sccp.c index 67e0a53..ba02a5e 100644 --- a/src/osmo-hnbgw/hnbgw_sccp.c +++ b/src/osmo-hnbgw/hnbgw_sccp.c @@ -332,18 +332,70 @@ return rc; } - -struct hnbgw_sccp_user *hnbgw_sccp_user_alloc(const struct hnbgw_cnlink *cnlink, int ss7_id) +static int hnbgw_sccp_user_use_cb(struct osmo_use_count_entry *e, int32_t old_use_count, const char *file, int line) { - struct osmo_ss7_instance *ss7 = NULL; + struct hnbgw_sccp_user *hsu = e->use_count->talloc_object; + int32_t total; + int level; + + if (!e->use) + return -EINVAL; + + total = osmo_use_count_total(&hsu->use_count); + + if (total == 0 + || (total == 1 && old_use_count == 0 && e->count == 1)) + level = LOGL_INFO; + else + level = LOGL_DEBUG; + + LOGPSRC(DCN, level, file, line, + "%s: %s %s: now used by %s\n", + hsu->name, + (e->count - old_use_count) > 0 ? "+" : "-", + e->use, + osmo_use_count_to_str_c(OTC_SELECT, &hsu->use_count)); + + if (e->count < 0) + return -ERANGE; + + if (total == 0) + talloc_free(hsu); + return 0; +} + +static int hnbgw_sccp_user_talloc_destructor(struct hnbgw_sccp_user *hsu) +{ + if (hsu->sccp_user) { + osmo_sccp_user_unbind(hsu->sccp_user); + hsu->sccp_user = NULL; + } + llist_del(&hsu->entry); + return 0; +} + +struct hnbgw_sccp_user *hnbgw_sccp_user_alloc(int ss7_id) +{ struct osmo_sccp_instance *sccp; - struct osmo_sccp_user *sccp_user; uint32_t local_pc; struct hnbgw_sccp_user *hsu; + hsu = talloc_zero(g_hnbgw, struct hnbgw_sccp_user); + OSMO_ASSERT(hsu); + *hsu = (struct hnbgw_sccp_user){ + .name = talloc_asprintf(hsu, "cs7-%u-sccp-OsmoHNBGW", ss7_id), + .use_count = { + .talloc_object = hsu, + .use_cb = hnbgw_sccp_user_use_cb, + }, + }; + hash_init(hsu->hnbgw_context_map_by_conn_id); + llist_add_tail(&hsu->entry, &g_hnbgw->sccp.users); + talloc_set_destructor(hsu, hnbgw_sccp_user_talloc_destructor); + sccp = osmo_sccp_simple_client_on_ss7_id(g_hnbgw, ss7_id, - cnlink->name, + hsu->name, DEFAULT_PC_HNBGW, OSMO_SS7_ASP_PROT_M3UA, 0, @@ -351,40 +403,37 @@ -1, "localhost"); if (!sccp) { - LOG_CNLINK(cnlink, DCN, LOGL_ERROR, "Failed to configure SCCP on 'cs7 instance %u'\n", - ss7_id); - return NULL; + LOG_HSU(hsu, DCN, LOGL_ERROR, "Failed to configure SCCP on 'cs7 instance %u'\n", + ss7_id); + goto free_hsu_ret; } - ss7 = osmo_sccp_get_ss7(sccp); - LOG_CNLINK(cnlink, DCN, LOGL_NOTICE, "created SCCP instance on cs7 instance %u\n", osmo_ss7_instance_get_id(ss7)); + hsu->ss7 = osmo_sccp_get_ss7(sccp); + LOG_HSU(hsu, DCN, LOGL_NOTICE, "created SCCP instance on cs7 instance %u\n", osmo_ss7_instance_get_id(hsu->ss7)); /* Bind the SCCP user, using the cs7 instance's default point-code if one is configured, or osmo-hnbgw's default * local PC. */ - local_pc = osmo_ss7_instance_get_primary_pc(ss7); + local_pc = osmo_ss7_instance_get_primary_pc(hsu->ss7); if (!osmo_ss7_pc_is_valid(local_pc)) local_pc = DEFAULT_PC_HNBGW; - LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "binding OsmoHNBGW user to cs7 instance %u, local PC %u = %s\n", - osmo_ss7_instance_get_id(ss7), local_pc, osmo_ss7_pointcode_print(ss7, local_pc)); + LOG_HSU(hsu, DCN, LOGL_DEBUG, "binding OsmoHNBGW user to cs7 instance %u, local PC %u = %s\n", + osmo_ss7_instance_get_id(hsu->ss7), local_pc, osmo_ss7_pointcode_print(hsu->ss7, local_pc)); - sccp_user = osmo_sccp_user_bind_pc(sccp, "OsmoHNBGW", sccp_sap_up, OSMO_SCCP_SSN_RANAP, local_pc); - if (!sccp_user) { - LOGP(DCN, LOGL_ERROR, "Failed to init SCCP User\n"); - return NULL; + char *sccp_user_name = talloc_asprintf(hsu, "%s-RANAP", hsu->name); + hsu->sccp_user = osmo_sccp_user_bind_pc(sccp, sccp_user_name, sccp_sap_up, OSMO_SCCP_SSN_RANAP, local_pc); + talloc_free(sccp_user_name); + if (!hsu->sccp_user) { + LOG_HSU(hsu, DCN, LOGL_ERROR, "Failed to init SCCP User\n"); + goto free_hsu_ret; } - hsu = talloc_zero(cnlink, struct hnbgw_sccp_user); - *hsu = (struct hnbgw_sccp_user){ - .name = talloc_asprintf(hsu, "cs7-%u.sccp", osmo_ss7_instance_get_id(ss7)), - .ss7 = ss7, - .sccp_user = sccp_user, - }; osmo_sccp_make_addr_pc_ssn(&hsu->local_addr, local_pc, OSMO_SCCP_SSN_RANAP); - hash_init(hsu->hnbgw_context_map_by_conn_id); - osmo_sccp_user_set_priv(sccp_user, hsu); - - llist_add_tail(&hsu->entry, &g_hnbgw->sccp.users); + osmo_sccp_user_set_priv(hsu->sccp_user, hsu); return hsu; + +free_hsu_ret: + talloc_free(hsu); + return NULL; } -- To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/40246?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: merged Gerrit-Project: osmo-hnbgw Gerrit-Branch: master Gerrit-Change-Id: I524f6da8e5936135b2153def103d83cec6549f94 Gerrit-Change-Number: 40246 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pes...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <lafo...@osmocom.org> Gerrit-Reviewer: osmith <osm...@sysmocom.de> Gerrit-Reviewer: pespin <pes...@sysmocom.de>