From 6d1df9ad960e3359b97bb915907af93c1b4f15fc Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Tue, 22 Mar 2016 19:26:52 +0100 Subject: Add Iu paging Add iu_page_cs() and iu_page_ps() API, also add to libiudummy for linking in tests. Implement msc_paging_request() by calling iu_page_cs(). --- openbsc/include/openbsc/iu.h | 3 ++ openbsc/src/libiu/iu.c | 79 +++++++++++++++++++++++++++++++++++++ openbsc/src/libmsc/gsm_subscriber.c | 13 ++++-- openbsc/tests/libiudummy/iudummy.c | 12 ++++++ 4 files changed, 104 insertions(+), 3 deletions(-) diff --git a/openbsc/include/openbsc/iu.h b/openbsc/include/openbsc/iu.h index 4fde62431..3a7c9f9dd 100644 --- a/openbsc/include/openbsc/iu.h +++ b/openbsc/include/openbsc/iu.h @@ -42,6 +42,9 @@ void iu_link_del(struct osmo_sua_link *link); int iu_tx(struct msgb *msg, uint8_t sapi); +int iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac); +int iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, uint8_t rac); + int iu_rab_act_cs(struct ue_conn_ctx *ue_ctx, uint32_t rtp_ip, uint16_t rtp_port); int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp); int iu_rab_deact(struct ue_conn_ctx *ue_ctx, uint8_t rab_id); diff --git a/openbsc/src/libiu/iu.c b/openbsc/src/libiu/iu.c index dcc281adb..b3e489dc1 100644 --- a/openbsc/src/libiu/iu.c +++ b/openbsc/src/libiu/iu.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,7 @@ #include #include +#include #include #include @@ -535,6 +537,83 @@ static void cn_ranap_handle_cl(void *ctx, ranap_message *message) } } +/*********************************************************************** + * Paging + ***********************************************************************/ + +/* Send a paging command down a given SUA link. 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. */ +static int iu_tx_paging_cmd(struct osmo_sua_link *link, + 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_ranap(link, 1, 2, msg->data, + msgb_length(msg)); +} + +static int iu_page(const char *imsi, const uint32_t *tmsi_or_ptimsi, + uint16_t lac, uint8_t rac, bool is_ps) +{ + struct iu_rnc *rnc; + int pagings_sent = 0; + + llist_for_each_entry(rnc, &rnc_list, entry) { + if (!rnc->link) { + /* Not actually connected, don't count it. */ + continue; + } + if (rnc->lac != lac) + continue; + if (is_ps && rnc->rac != rac) + continue; + + /* Found a match! */ + if (iu_tx_paging_cmd(rnc->link, imsi, tmsi_or_ptimsi, is_ps, 0) + == 0) + pagings_sent ++; + } + + /* Some logging... */ + if (pagings_sent > 0) { + LOGP(DRANAP, LOGL_DEBUG, + "%s: %d RNCs were paged for IMSI %s.\n", + is_ps? "IuPS" : "IuCS", + pagings_sent, imsi); + } + else { + if (is_ps) { + LOGP(DRANAP, LOGL_ERROR, "IuPS: Found no RNC to page for" + " LAC %d RAC %d (would have paged IMSI %s)\n", + lac, rac, imsi); + } + else { + LOGP(DRANAP, LOGL_ERROR, "IuCS: Found no RNC to page for" + " LAC %d (would have paged IMSI %s)\n", + lac, imsi); + } + } + + return pagings_sent; +} + +int iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac) +{ + return iu_page(imsi, tmsi, lac, 0, false); +} + +int iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, uint8_t rac) +{ + return iu_page(imsi, ptmsi, lac, rac, true); +} + + /*********************************************************************** * ***********************************************************************/ diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c index b08e27fbc..39b544b90 100644 --- a/openbsc/src/libmsc/gsm_subscriber.c +++ b/openbsc/src/libmsc/gsm_subscriber.c @@ -38,6 +38,7 @@ #include #include #include +#include void *tall_sub_req_ctx; @@ -168,9 +169,15 @@ static int subscr_paging_cb(unsigned int hooknum, unsigned int event, int msc_paging_request(struct gsm_network *network, struct gsm_subscriber *subscr, int type, gsm_cbfn *cbfn, void *data) { - LOGP(DMM, LOGL_ERROR, "MSC paging not implemented! want to page %s\n", - subscr_name(subscr)); - return -1; + /* The subscriber was last seen in subscr->lac. Find out which + * BSCs/RNCs are responsible and send them a paging request via open + * SCCP connections (if any). */ + /* TODO Implementing only RNC paging, since this is code on the iu branch. + * Need to add BSC paging at some point. */ + return iu_page_cs(subscr->imsi, + subscr->tmsi == GSM_RESERVED_TMSI? + NULL : &subscr->tmsi, + subscr->lac); } struct subscr_request *subscr_request_channel(struct gsm_subscriber *subscr, diff --git a/openbsc/tests/libiudummy/iudummy.c b/openbsc/tests/libiudummy/iudummy.c index 770bccaa9..7052de82c 100644 --- a/openbsc/tests/libiudummy/iudummy.c +++ b/openbsc/tests/libiudummy/iudummy.c @@ -21,3 +21,15 @@ int iu_tx_sec_mode_cmd(struct ue_conn_ctx *uectx, struct gsm_auth_tuple *tp, LOGP(DLGLOBAL, LOGL_INFO, "iu_tx_sec_mode_cmd() dummy called, NOT transmitting Security Mode Command\n"); return 0; } + +int iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac) +{ + LOGP(DLGLOBAL, LOGL_INFO, "iu_page_cs() dummy called, NOT paging\n"); + return 0; +} + +int iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, uint8_t rac) +{ + LOGP(DLGLOBAL, LOGL_INFO, "iu_page_ps() dummy called, NOT paging\n"); + return 0; +} -- cgit v1.2.3