aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2016-03-22 19:26:52 +0100
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2016-04-20 11:22:59 +0200
commit6d1df9ad960e3359b97bb915907af93c1b4f15fc (patch)
tree6f6a5100c940d9927d5d46e20f428852a3adedd8 /openbsc
parent9bc1ddc849714bd4f38ce9d40965793ff400606b (diff)
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().
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/iu.h3
-rw-r--r--openbsc/src/libiu/iu.c79
-rw-r--r--openbsc/src/libmsc/gsm_subscriber.c13
-rw-r--r--openbsc/tests/libiudummy/iudummy.c12
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 <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <stdbool.h>
#include <osmocom/core/select.h>
#include <osmocom/core/prim.h>
@@ -16,6 +17,7 @@
#include <osmocom/sigtran/sua.h>
#include <osmocom/sigtran/sccp_sap.h>
+#include <osmocom/sigtran/sccp_helpers.h>
#include <openbsc/gprs_sgsn.h>
#include <openbsc/iu.h>
@@ -536,6 +538,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 <openbsc/signal.h>
#include <openbsc/db.h>
#include <openbsc/chan_alloc.h>
+#include <openbsc/iu.h>
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;
+}