lynxis lazus submitted this change.

View Change

Approvals: pespin: Looks good to me, approved laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified
libvlr: add PVLR support

Allow to retrieve information from the PVLR (Previous VLR).
In case of PS/SGSN this can be another SGSN or a MME.
Introduce a new callback for CS and PS to check if the LAI or RAI
is currently served.

Change-Id: I189c041dbc3a33ad15746092691cb382d1911495
---
M include/osmocom/vlr/vlr.h
M src/libmsc/gsm_04_08.c
M src/libvlr/vlr.c
M src/libvlr/vlr_lu_fsm.c
4 files changed, 80 insertions(+), 17 deletions(-)

diff --git a/include/osmocom/vlr/vlr.h b/include/osmocom/vlr/vlr.h
index 55d237e..d0db4c0 100644
--- a/include/osmocom/vlr/vlr.h
+++ b/include/osmocom/vlr/vlr.h
@@ -252,6 +252,9 @@

int (*tx_mm_info)(void *msc_conn_ref);

+ int (*tx_pvlr_request_rai)(void *msc_conn_ref, const struct osmo_routing_area_id *old_rai);
+ int (*tx_pvlr_request_lai)(void *msc_conn_ref, const struct osmo_location_area_id *old_lai);
+
/* notify MSC/SGSN that the subscriber data in VLR has been updated */
void (*subscr_update)(struct vlr_subscr *vsub);
/* notify MSC/SGSN that the given subscriber has been associated
@@ -259,6 +262,10 @@
int (*subscr_assoc)(void *msc_conn_ref, struct vlr_subscr *vsub);
/* notify MSC that the given subscriber is no longer valid. */
void (*subscr_inval)(void *msc_conn_ref, struct vlr_subscr *vsub, enum vlr_inval_reason reason);
+
+ /* decide if the location/routing area id is within the VLR or not */
+ bool (*location_area_served)(struct vlr_subscr *vsub, const struct osmo_location_area_id *lai);
+ bool (*routing_area_served)(struct vlr_subscr *vsub, const struct osmo_routing_area_id *rai);
};

/* An instance of the VLR codebase */
@@ -341,6 +348,9 @@
int vlr_subscr_rx_tmsi_reall_compl(struct vlr_subscr *vsub);
int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub);
int vlr_subscr_rx_rau_complete(struct vlr_subscr *vsub);
+void vlr_subscr_rx_pvlr_id_ack(struct vlr_subscr *vsub);
+void vlr_subscr_rx_pvlr_id_nack(struct vlr_subscr *vsub);
+

struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops, bool is_ps);
int vlr_start(struct vlr_instance *vlr, struct gsup_client_mux *gcm);
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
index 7a63220..6f5e7cd 100644
--- a/src/libmsc/gsm_04_08.c
+++ b/src/libmsc/gsm_04_08.c
@@ -1590,6 +1590,17 @@
}
}

+/* TODO: implement correct location served cb */
+static bool msc_vlr_location_area_served(struct vlr_subscr *vsub, const struct osmo_location_area_id *lai)
+{
+ return true;
+}
+
+static int msc_vlr_tx_pvlr_request_lai(void *msc_conn_ref, const struct osmo_location_area_id *lai)
+{
+ return -ENOTSUP;
+}
+
/* operations that we need to implement for libvlr */
const struct vlr_ops msc_vlr_ops = {
.tx_auth_req = msc_vlr_tx_auth_req,
@@ -1602,9 +1613,11 @@
.set_ciph_mode = msc_a_vlr_set_cipher_mode,
.tx_common_id = msc_vlr_tx_common_id,
.tx_mm_info = msc_vlr_tx_mm_info,
+ .tx_pvlr_request_lai = msc_vlr_tx_pvlr_request_lai,
.subscr_update = msc_vlr_subscr_update,
.subscr_assoc = msc_vlr_subscr_assoc,
.subscr_inval = msc_vlr_subscr_inval,
+ .location_area_served = msc_vlr_location_area_served,
};

struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value)
diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c
index 6ddd8bc..5baf2c3 100644
--- a/src/libvlr/vlr.c
+++ b/src/libvlr/vlr.c
@@ -1540,6 +1540,23 @@
return vlr_subscr_detach(vsub);
}

+void vlr_subscr_rx_pvlr_id_ack(struct vlr_subscr *vsub)
+{
+ if (!vsub->lu_fsm)
+ return;
+
+ osmo_fsm_inst_dispatch(vsub->lu_fsm, VLR_ULA_E_SEND_ID_ACK, NULL);
+}
+
+void vlr_subscr_rx_pvlr_id_nack(struct vlr_subscr *vsub)
+{
+ if (!vsub->lu_fsm)
+ return;
+
+ osmo_fsm_inst_dispatch(vsub->lu_fsm, VLR_ULA_E_SEND_ID_NACK, NULL);
+}
+
+
/* Tear down any running FSMs due to MSC connection timeout.
* Visit all vsub->*_fsm pointers and give them a queue to send a final reject
* message before the entire connection is torn down.
@@ -1569,6 +1586,12 @@
OSMO_ASSERT(ops->subscr_update);
OSMO_ASSERT(ops->subscr_assoc);

+ OSMO_ASSERT(is_ps || ops->location_area_served);
+ OSMO_ASSERT(is_ps || ops->tx_pvlr_request_lai);
+
+ OSMO_ASSERT(!is_ps || ops->routing_area_served);
+ OSMO_ASSERT(!is_ps || ops->tx_pvlr_request_rai);
+
INIT_LLIST_HEAD(&vlr->subscribers);
INIT_LLIST_HEAD(&vlr->operations);
memcpy(&vlr->ops, ops, sizeof(vlr->ops));
diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c
index 8fa6c54..e9435e3 100644
--- a/src/libvlr/vlr_lu_fsm.c
+++ b/src/libvlr/vlr_lu_fsm.c
@@ -776,15 +776,6 @@
int N;
};

-
-/* Determine if given location area is served by this VLR */
-static bool lai_in_this_vlr(struct vlr_instance *vlr,
- const struct osmo_location_area_id *lai)
-{
- /* TODO: VLR needs to keep a locally configured list of LAIs */
- return true;
-}
-
/* Return true when authentication should be attempted. */
static bool try_auth(struct lu_fsm_priv *lfp)
{
@@ -1136,6 +1127,16 @@
return 0;
}

+/* Determine if given location area is served by this VLR */
+static bool location_served(struct vlr_instance *vlr,
+ struct lu_fsm_priv *lfp)
+{
+ if (vlr_is_cs(vlr))
+ return vlr->ops.location_area_served(lfp->vsub, &lfp->old_lai);
+ else
+ return vlr->ops.routing_area_served(lfp->vsub, &lfp->old_rai);
+}
+
/* 4.1.2.1: Subscriber (via MSC/SGSN) requests location update */
static void _start_lu_main(struct osmo_fsm_inst *fi)
{
@@ -1145,16 +1146,10 @@
/* TODO: PUESBINE related handling */

/* Is previous LAI in this VLR? */
- if (!lai_in_this_vlr(vlr, &lfp->old_lai)) {
-#if 0
- /* FIXME: check previous VLR, (3) */
+ if (!location_served(vlr, lfp)) {
osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_PVLR,
LU_TIMEOUT_LONG, 0);
return;
-#endif
- LOGPFSML(fi, LOGL_NOTICE, "LAI change from %s,"
- " but checking previous VLR not implemented\n",
- osmo_lai_name(&lfp->old_lai));
}

/* If this is a TMSI based LU, we may not have the IMSI. Make sure that
@@ -1209,16 +1204,37 @@
}
}

+static void lu_fsm_wait_pvlr_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
+ struct vlr_instance *vlr = lfp->vlr;
+
+ if (vlr_is_cs(vlr))
+ vlr->ops.tx_pvlr_request_lai(lfp->msc_conn_ref, &lfp->old_lai);
+ else
+ vlr->ops.tx_pvlr_request_rai(lfp->msc_conn_ref, &lfp->old_rai);
+}
+
/* Wait for response from Send_Identification to PVLR */
static void lu_fsm_wait_pvlr(struct osmo_fsm_inst *fi, uint32_t event,
void *data)
{
+ struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
+
switch (event) {
case VLR_ULA_E_SEND_ID_ACK:
vlr_loc_upd_node1_pre(fi);
break;
case VLR_ULA_E_SEND_ID_NACK:
- vlr_loc_upd_want_imsi(fi);
+ if (vlr_is_cs(lfp->vlr)) {
+ vlr_loc_upd_want_imsi(fi);
+ break;
+ }
+ /* PS */
+ if (lfp->lu_type == VLR_LU_TYPE_IMSI_ATTACH)
+ vlr_loc_upd_want_imsi(fi);
+ else
+ lu_fsm_failure(fi, GSM48_REJECT_MS_IDENTITY_NOT_DERVIVABLE);
break;
default:
OSMO_ASSERT(0);
@@ -1476,6 +1492,7 @@
S(VLR_ULA_S_WAIT_HLR_CHECK_IMEI_EARLY) |
S(VLR_ULA_S_DONE),
.name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_PVLR),
+ .onenter = lu_fsm_wait_pvlr_onenter,
.action = lu_fsm_wait_pvlr,
},
[VLR_ULA_S_WAIT_AUTH] = {

To view, visit change 43479. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: merged
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: I189c041dbc3a33ad15746092691cb382d1911495
Gerrit-Change-Number: 43479
Gerrit-PatchSet: 4
Gerrit-Owner: lynxis lazus <lynxis@fe80.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: lynxis lazus <lynxis@fe80.eu>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>