pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-sgsn/+/41001?usp=email )
Change subject: ranap: Take into account RNC availability during paging ...................................................................... ranap: Take into account RNC availability during paging Avoid transmitting a RANAP paging message to an RNC if we already know it's not currently available over SCCP. Take into account that information when deciding/printing whether the paging could be sent or not. Take the chance to clean up the iu paging function helpers inherited from osmo-iuh iu_client.c to better fit the data domain in osmo-sgsn (iu_rnc). Change-Id: I24e5446bcf4c958028577230b231960acea9e5b9 --- M include/osmocom/sgsn/gprs_ranap.h M include/osmocom/sgsn/iu_rnc.h M include/osmocom/sgsn/iu_rnc_fsm.h M src/sgsn/gprs_ranap.c M src/sgsn/iu_client.c M src/sgsn/iu_rnc.c M src/sgsn/iu_rnc_fsm.c 7 files changed, 144 insertions(+), 115 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-sgsn refs/changes/01/41001/1 diff --git a/include/osmocom/sgsn/gprs_ranap.h b/include/osmocom/sgsn/gprs_ranap.h index 62914ba..b959b57 100644 --- a/include/osmocom/sgsn/gprs_ranap.h +++ b/include/osmocom/sgsn/gprs_ranap.h @@ -30,9 +30,6 @@ int sgsn_ranap_iu_tx_sec_mode_cmd(struct ranap_ue_conn_ctx *uectx, struct osmo_auth_vector *vec, int send_ck, int new_key); int sgsn_ranap_iu_tx_common_id(struct ranap_ue_conn_ctx *ue_ctx, const char *imsi); -int sgsn_ranap_iu_tx_paging_cmd(struct osmo_sccp_addr *called_addr, - const char *imsi, const uint32_t *tmsi, - bool is_ps, uint32_t paging_cause); int sgsn_ranap_iu_tx_release(struct ranap_ue_conn_ctx *ctx, const struct RANAP_Cause *cause); /* Transmit a Iu Release Command and submit event RANAP_IU_EVENT_IU_RELEASE upon diff --git a/include/osmocom/sgsn/iu_rnc.h b/include/osmocom/sgsn/iu_rnc.h index b0e5be3..0382b74 100644 --- a/include/osmocom/sgsn/iu_rnc.h +++ b/include/osmocom/sgsn/iu_rnc.h @@ -1,6 +1,7 @@ #pragma once #include <stdbool.h> +#include <stdint.h> #include <osmocom/core/defs.h> #include <osmocom/core/linuxlist.h> @@ -43,6 +44,12 @@ void iu_rnc_discard_all_ue_ctx(struct ranap_iu_rnc *rnc); +int iu_rnc_tx_paging_cmd(struct ranap_iu_rnc *rnc, + const char *imsi, + const uint32_t *tmsi, + bool is_ps, + uint32_t paging_cause); + #define LOG_RNC_CAT(IU_RNC, subsys, loglevel, fmt, args ...) \ LOGPFSMSL((IU_RNC)->fi, subsys, loglevel, fmt, ## args) diff --git a/include/osmocom/sgsn/iu_rnc_fsm.h b/include/osmocom/sgsn/iu_rnc_fsm.h index d9be576..f69d82e 100644 --- a/include/osmocom/sgsn/iu_rnc_fsm.h +++ b/include/osmocom/sgsn/iu_rnc_fsm.h @@ -29,6 +29,7 @@ IU_RNC_EV_MSG_UP_CO, /* struct iu_rnc_ev_msg_up_co_ctx* */ IU_RNC_EV_RX_RESET, /* no param */ IU_RNC_EV_RX_RESET_ACK, /* no param */ + IU_RNC_EV_MSG_DOWN_CL, /* struct msgb* */ IU_RNC_EV_AVAILABLE, IU_RNC_EV_UNAVAILABLE }; diff --git a/src/sgsn/gprs_ranap.c b/src/sgsn/gprs_ranap.c index df9cc9e..1cdb72b 100644 --- a/src/sgsn/gprs_ranap.c +++ b/src/sgsn/gprs_ranap.c @@ -287,22 +287,6 @@ return sgsn_scu_iups_tx_data_req(uectx->rnc->scu_iups, uectx->conn_id, msg); } -/* Send a paging command down a given SCCP User. tmsi and paging_cause are - * optional and may be passed NULL and 0, respectively, to disable their use. - * See enum RANAP_PagingCause. - * - * If TMSI is given, the IMSI is not sent over the air interface. Nevertheless, - * the IMSI is still required for resolution in the HNB-GW and/or(?) RNC. */ -int sgsn_ranap_iu_tx_paging_cmd(struct osmo_sccp_addr *called_addr, - const char *imsi, const uint32_t *tmsi, - bool is_ps, uint32_t paging_cause) -{ - struct msgb *msg; - msg = ranap_new_msg_paging_cmd(imsi, tmsi, is_ps ? 1 : 0, paging_cause); - msg->l2h = msg->data; - return osmo_sccp_tx_unitdata_msg(sgsn->sccp.scu_iups->scu, &sgsn->sccp.scu_iups->local_sccp_addr, called_addr, msg); -} - int sgsn_ranap_iu_tx(struct msgb *msg_nas, uint8_t sapi) { struct ranap_ue_conn_ctx *uectx = msg_nas->dst; diff --git a/src/sgsn/iu_client.c b/src/sgsn/iu_client.c index cb5d096..164ff71 100644 --- a/src/sgsn/iu_client.c +++ b/src/sgsn/iu_client.c @@ -43,12 +43,6 @@ #include <osmocom/sgsn/sccp.h> #include <osmocom/sgsn/sgsn.h> -#define LOGPIU(level, fmt, args...) \ - LOGP(DRANAP, level, fmt, ## args) - -#define LOGPIUC(level, fmt, args...) \ - LOGPC(DRANAP, level, fmt, ## args) - const struct value_string iu_client_event_type_names[] = { OSMO_VALUE_STRING(RANAP_IU_EVENT_RAB_ASSIGN), OSMO_VALUE_STRING(RANAP_IU_EVENT_SECURITY_MODE_COMPLETE), @@ -66,7 +60,7 @@ if (ue_ctx && !ue_ctx->notification) return 0; - LOGPIU(LOGL_DEBUG, "Submit Iu event to upper layer: %s\n", iu_client_event_type_str(type)); + LOGP(DRANAP, LOGL_DEBUG, "Submit Iu event to upper layer: %s\n", iu_client_event_type_str(type)); return sgsn_ranap_iu_event(ue_ctx, type, data); } @@ -126,78 +120,74 @@ ***********************************************************************/ /* legacy, do a first match with ignoring PLMN */ -static bool iu_rnc_lac_rac_find_legacy(struct ranap_iu_rnc **rnc, struct iu_lac_rac_entry **lre, - uint16_t lac, uint8_t rac) -{ - struct ranap_iu_rnc *r; - struct iu_lac_rac_entry *e; - - if (rnc) - *rnc = NULL; - if (lre) - *lre = NULL; - - llist_for_each_entry(r, &sgsn->rnc_list, entry) { - llist_for_each_entry(e, &r->lac_rac_list, entry) { - if (e->rai.lac.lac == lac && e->rai.rac == rac) { - if (rnc) - *rnc = r; - if (lre) - *lre = e; - return true; - } - } - } - return false; -} - -static int iu_page(const char *imsi, const uint32_t *tmsi_or_ptmsi, - uint16_t lac, uint8_t rac, bool is_ps) +static struct ranap_iu_rnc *iu_rnc_lac_rac_find_legacy(uint16_t lac, uint8_t rac) { struct ranap_iu_rnc *rnc; - const char *log_msg; - int log_level; - int paged = 0; + struct iu_lac_rac_entry *e; - iu_rnc_lac_rac_find_legacy(&rnc, NULL, lac, rac); - if (rnc) { - if (sgsn_ranap_iu_tx_paging_cmd(&rnc->sccp_addr, imsi, tmsi_or_ptmsi, is_ps, 0) == 0) { - log_msg = "Paging"; - log_level = LOGL_DEBUG; - paged = 1; - } else { - log_msg = "Paging failed"; - log_level = LOGL_ERROR; + llist_for_each_entry(rnc, &sgsn->rnc_list, entry) { + llist_for_each_entry(e, &rnc->lac_rac_list, entry) { + if (e->rai.lac.lac == lac && e->rai.rac == rac) + return rnc; } - } else { - log_msg = "Found no RNC to Page"; - log_level = LOGL_ERROR; } - - if (is_ps) - LOGPIU(log_level, "IuPS: %s on LAC %d RAC %d", log_msg, lac, rac); - else - LOGPIU(log_level, "IuCS: %s on LAC %d", log_msg, lac); - if (rnc) - LOGPIUC(log_level, " at SCCP-addr %s", osmo_sccp_addr_dump(&rnc->sccp_addr)); - if (tmsi_or_ptmsi) - LOGPIUC(log_level, ", for %s %08x\n", is_ps ? "PTMSI" : "TMSI", *tmsi_or_ptmsi); - else - LOGPIUC(log_level, ", for IMSI %s\n", imsi); - - return paged; + return NULL; } /*! Old paging() doesn't use PLMN and transmit paging command only to the first RNC */ int ranap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac) { - return iu_page(imsi, tmsi, lac, 0, false); + struct ranap_iu_rnc *rnc; + char log_msg[32] = {}; + int rc; + + if (tmsi) + snprintf(log_msg, sizeof(log_msg), "TMSI %08x\n", *tmsi); + else + snprintf(log_msg, sizeof(log_msg), "IMSI %s\n", imsi); + + rnc = iu_rnc_lac_rac_find_legacy(lac, 0); + if (!rnc) { + LOGP(DRANAP, LOGL_INFO, "Found no RNC to Page CS on LAC %u for %s", + lac, log_msg); + return 0; + } + + rc = iu_rnc_tx_paging_cmd(rnc, imsi, tmsi, false, 0); + if (rc != 0) { + LOG_RNC(rnc, LOGL_ERROR, "Failed to tx Paging CS for LAC %u for %s", + lac, log_msg); + return 0; + } + return 1; } /*! Old paging() doesn't use PLMN and transmit paging command only to the first RNC */ int ranap_iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, uint8_t rac) { - return iu_page(imsi, ptmsi, lac, rac, true); + struct ranap_iu_rnc *rnc; + char log_msg[32] = {}; + int rc; + + if (ptmsi) + snprintf(log_msg, sizeof(log_msg), "P-TMSI %08x\n", *ptmsi); + else + snprintf(log_msg, sizeof(log_msg), "IMSI %s\n", imsi); + + rnc = iu_rnc_lac_rac_find_legacy(lac, rac); + if (!rnc) { + LOGP(DRANAP, LOGL_INFO, "Found no RNC to Page PS on LAC %u RAC %u for %s", + lac, rac, log_msg); + return 0; + } + + rc = iu_rnc_tx_paging_cmd(rnc, imsi, ptmsi, true, 0); + if (rc != 0) { + LOG_RNC(rnc, LOGL_ERROR, "Failed to tx Paging PS for LAC %u RAC %u for %s", + lac, rac, log_msg); + return 0; + } + return 1; } /*! Transmit a single page request towards all RNCs serving the specific LAI (no page retransmission). @@ -212,8 +202,13 @@ struct ranap_iu_rnc *rnc; struct iu_lac_rac_entry *entry; char log_msg[32] = {}; - int paged = 0; - int rc = 0; + unsigned int paged = 0; + int rc; + + if (tmsi) + snprintf(log_msg, sizeof(log_msg), "TMSI %08x\n", *tmsi); + else + snprintf(log_msg, sizeof(log_msg), "IMSI %s\n", imsi); /* find all RNCs which are serving this LA */ llist_for_each_entry(rnc, &sgsn->rnc_list, entry) { @@ -221,27 +216,23 @@ if (osmo_lai_cmp(&entry->rai.lac, lai)) continue; - rc = sgsn_ranap_iu_tx_paging_cmd(&rnc->sccp_addr, imsi, tmsi, false, 0); - if (rc > 0) { - LOGPIU(LOGL_ERROR, "IuCS: Failed to tx Paging RNC %s for LAC %s for IMSI %s / TMSI %08x", - osmo_rnc_id_name(&rnc->rnc_id), - osmo_lai_name(lai), imsi, tmsi ? *tmsi : GSM_RESERVED_TMSI); + rc = iu_rnc_tx_paging_cmd(rnc, imsi, tmsi, false, 0); + if (rc != 0) { + LOG_RNC(rnc, LOGL_ERROR, "Failed to tx Paging CS for LAI %s for %s", + osmo_lai_name(lai), log_msg); + } else { + paged++; } - paged++; break; } } - if (tmsi) - snprintf(log_msg, sizeof(log_msg), "for TMSI %08x\n", *tmsi); - else - snprintf(log_msg, sizeof(log_msg) - 1, "for IMSI %s\n", imsi); - if (paged) - LOGPIU(LOGL_DEBUG, "IuPS: Paged %d RNCs on LAI %s for %s", paged, osmo_lai_name(lai), log_msg); + LOGP(DRANAP, LOGL_DEBUG, "Paged CS %u RNCs on LAI %s for %s", + paged, osmo_lai_name(lai), log_msg); else - LOGPIU(LOGL_INFO, "IuPS: Found no RNC to Page on LAI %s for %s", osmo_lai_name(lai), log_msg); - + LOGP(DRANAP, LOGL_INFO, "Found no RNC to Page CS on LAI %s for %s", + osmo_lai_name(lai), log_msg); return paged; } @@ -249,7 +240,7 @@ /*! Transmit a single page request towards all RNCs serving the specific RAI (no page retransmission). * * \param imsi the imsi as human readable string - * \param ptmsi NULL or pointer to the tmsi + * \param ptmsi NULL or pointer to the ptmsi * \param rai full Location Area Identifier * \return amount of paged RNCs. 0 when no RNC found. */ @@ -258,8 +249,13 @@ struct ranap_iu_rnc *rnc; struct iu_lac_rac_entry *entry; char log_msg[32] = {}; - int paged = 0; - int rc = 0; + unsigned int paged = 0; + int rc; + + if (ptmsi) + snprintf(log_msg, sizeof(log_msg), "P-TMSI %08x\n", *ptmsi); + else + snprintf(log_msg, sizeof(log_msg), "IMSI %s\n", imsi); /* find all RNCs which are serving this RAC */ llist_for_each_entry(rnc, &sgsn->rnc_list, entry) { @@ -267,26 +263,23 @@ if (osmo_rai_cmp(&entry->rai, rai)) continue; - rc = sgsn_ranap_iu_tx_paging_cmd(&rnc->sccp_addr, imsi, ptmsi, true, 0); - if (rc > 0) { - LOGPIU(LOGL_ERROR, "IuPS: Failed to tx Paging RNC %s for RAC %s for IMSI %s / P-TMSI %08x", - osmo_rnc_id_name(&rnc->rnc_id), - osmo_rai_name2(rai), imsi, ptmsi ? *ptmsi : GSM_RESERVED_TMSI); + rc = iu_rnc_tx_paging_cmd(rnc, imsi, ptmsi, true, 0); + if (rc != 0) { + LOG_RNC(rnc, LOGL_ERROR, "Failed to tx Paging PS for RAI %s for %s", + osmo_rai_name2(rai), log_msg); + } else { + paged++; } - paged++; break; } } - if (ptmsi) - snprintf(log_msg, sizeof(log_msg) - 1, "for PTMSI %08x\n", *ptmsi); - else - snprintf(log_msg, sizeof(log_msg) - 1, "for IMSI %s\n", imsi); - if (paged) - LOGPIU(LOGL_DEBUG, "IuPS: Paged %d RNCs on RAI %s for %s", paged, osmo_rai_name2(rai), log_msg); + LOGP(DRANAP, LOGL_DEBUG, "Paged PS %u RNCs on RAI %s for %s", + paged, osmo_rai_name2(rai), log_msg); else - LOGPIU(LOGL_INFO, "IuPS: Found no RNC to Page on RAI %s for %s", osmo_rai_name2(rai), log_msg); + LOGP(DRANAP, LOGL_INFO, "Found no RNC to Page PS on RAI %s for %s", + osmo_rai_name2(rai), log_msg); return paged; } diff --git a/src/sgsn/iu_rnc.c b/src/sgsn/iu_rnc.c index 38cddb5..1a15df1 100644 --- a/src/sgsn/iu_rnc.c +++ b/src/sgsn/iu_rnc.c @@ -213,3 +213,43 @@ ue_conn_ctx_link_invalidated_free(ue_ctx); } } + +/* Send a paging command down a given SCCP User. tmsi_or_ptmsi and paging_cause are + * optional and may be passed NULL and 0, respectively, to disable their use. + * See enum RANAP_PagingCause. + * + * If tmsi_or_ptmsi is given, the imsi is not sent over the air interface. + * Nevertheless, the IMSI is still required for resolution in the HNB-GW + * and/or(?) RNC. + * + * returns negative if paging couldn't be sent (eg. because RNC is currently + * unreachable in lower layers). + **/ +int iu_rnc_tx_paging_cmd(struct ranap_iu_rnc *rnc, + const char *imsi, + const uint32_t *tmsi_or_ptmsi, + bool is_ps, + uint32_t paging_cause) +{ + struct msgb *ranap_msg; + int rc; + + /* rnc is not ready for paging (link not ready). */ + if (rnc->fi->state != IU_RNC_ST_READY) + return -ENOLINK; + + LOG_RNC(rnc, LOGL_DEBUG, "Paging %s for %s=%08x IMSI=%s\n", + is_ps ? "PS" : "CS", + is_ps ? "P-TMSI" : "TMSI", + tmsi_or_ptmsi ? *tmsi_or_ptmsi : GSM_RESERVED_TMSI, + imsi); + + ranap_msg = ranap_new_msg_paging_cmd(imsi, tmsi_or_ptmsi, is_ps ? 1 : 0, paging_cause); + if (!ranap_msg) + return -EINVAL; + + rc = osmo_fsm_inst_dispatch(rnc->fi, IU_RNC_EV_MSG_DOWN_CL, ranap_msg); + if (rc != 0) + msgb_free(ranap_msg); + return rc; +} diff --git a/src/sgsn/iu_rnc_fsm.c b/src/sgsn/iu_rnc_fsm.c index 6f610b4..6b0ad41 100644 --- a/src/sgsn/iu_rnc_fsm.c +++ b/src/sgsn/iu_rnc_fsm.c @@ -57,6 +57,7 @@ OSMO_VALUE_STRING(IU_RNC_EV_MSG_UP_CO), OSMO_VALUE_STRING(IU_RNC_EV_RX_RESET), OSMO_VALUE_STRING(IU_RNC_EV_RX_RESET_ACK), + OSMO_VALUE_STRING(IU_RNC_EV_MSG_DOWN_CL), OSMO_VALUE_STRING(IU_RNC_EV_AVAILABLE), OSMO_VALUE_STRING(IU_RNC_EV_UNAVAILABLE), {} @@ -252,6 +253,11 @@ iu_rnc_rx_reset(rnc); return; + case IU_RNC_EV_MSG_DOWN_CL: + OSMO_ASSERT(data); + sgsn_ranap_iu_tx_cl(rnc->scu_iups, &rnc->sccp_addr, (struct msgb *)data); + return; + case IU_RNC_EV_AVAILABLE: /* Do nothing, we were already up. */ return; @@ -336,6 +342,7 @@ | S(IU_RNC_EV_RX_RESET) | S(IU_RNC_EV_MSG_UP_CO_INITIAL) | S(IU_RNC_EV_MSG_UP_CO) + | S(IU_RNC_EV_MSG_DOWN_CL) | S(IU_RNC_EV_AVAILABLE) | S(IU_RNC_EV_UNAVAILABLE) , -- To view, visit https://gerrit.osmocom.org/c/osmo-sgsn/+/41001?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: osmo-sgsn Gerrit-Branch: master Gerrit-Change-Id: I24e5446bcf4c958028577230b231960acea9e5b9 Gerrit-Change-Number: 41001 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pes...@sysmocom.de>