lynxis lazus has submitted this change. ( https://gerrit.osmocom.org/c/osmo-msc/+/43479?usp=email )
Change subject: libvlr: add PVLR support ......................................................................
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(-)
Approvals: pespin: Looks good to me, approved laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified
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] = {