lynxis lazus has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-msc/+/38490?usp=email )


Change subject: vlr: add PS support
......................................................................

vlr: add PS support

Add vlr_ra_update() similar to vlr_lu_update().
Implement resending of GMM PDUs. While CS has a reliable connection
between the MS and MSC, the MS and SGSN doesn't have such connection.
The PDU is resend N times before the LU fsm is failing.

Change-Id: Ie9ffeb140c9d354b3a0f4822e2619f623235add0
---
M src/libvlr/vlr.c
M src/libvlr/vlr_lu_fsm.c
2 files changed, 214 insertions(+), 2 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/90/38490/1

diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c
index c7d17f8..b8650c7 100644
--- a/src/libvlr/vlr.c
+++ b/src/libvlr/vlr.c
@@ -1480,6 +1480,16 @@
        }
 }
 
+/* SGSN->VLR: Subscriber has provided ATTACH/RAU Complete */
+int vlr_subscr_rx_rau_complete(struct vlr_subscr *vsub)
+{
+       if (!vsub->lu_fsm)
+               return -EINVAL;
+
+       return osmo_fsm_inst_dispatch(vsub->lu_fsm,
+                                             VLR_ULA_E_NEW_TMSI_ACK, NULL);
+}
+
 bool vlr_subscr_expire(struct vlr_subscr *vsub)
 {
        if (vsub->lu_complete) {
diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c
index fca8347..fa0b83b 100644
--- a/src/libvlr/vlr_lu_fsm.c
+++ b/src/libvlr/vlr_lu_fsm.c
@@ -354,6 +354,7 @@
        uint8_t cause;
        bool assign_tmsi;
        enum vlr_lu_type lu_type;
+       int N; /*! counter of timeouts */
 };

 static inline struct lu_compl_vlr_priv *lu_compl_vlr_fi_priv(struct 
osmo_fsm_inst *fi);
@@ -407,6 +408,7 @@
        OSMO_ASSERT(vlr);

        OSMO_ASSERT(event == LU_COMPL_VLR_E_START);
+       lcvp->N = 0;

        /* TODO: National Roaming restrictions? */
        /* TODO: Roaming restriction due to unsupported feature in subscriber
@@ -564,6 +566,42 @@
        vlr_lu_compl_fsm_success(fi);
 }

+static void vlr_lu_compl_fsm_reset_n(struct osmo_fsm_inst *fi, uint32_t 
prev_state)
+{
+       struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
+       lcvp->N = 0;
+}
+
+static int lu_compl_vlr_timeout(struct osmo_fsm_inst *fi) {
+       struct lu_compl_vlr_priv *lcvp = lu_compl_vlr_fi_priv(fi);
+       struct vlr_instance *vlr = lcvp->vsub->vlr;
+       struct vlr_subscr *vsub = lcvp->vsub;
+
+       /* on cs: terminate the FSM */
+       if (vlr_is_cs(lcvp->vsub->vlr))
+               return 1;
+
+       /* PS: we have to resend the complete message 5x times, before failing 
*/
+       if (++lcvp->N >= 5)
+               return 1;
+
+       LOGPFSML(fi, LOGL_ERROR, "LU Compl timeout %i / %i \n", fi->T, lcvp->N);
+
+       switch (fi->state) {
+       case LU_COMPL_VLR_S_WAIT_IMEI:
+       case LU_COMPL_VLR_S_WAIT_IMEI_TMSI:
+               vlr->ops.tx_id_req(lcvp->msc_conn_ref, GSM_MI_TYPE_IMEI);
+               break;
+       case LU_COMPL_VLR_S_WAIT_TMSI_CNF:
+               vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, vsub->tmsi_new, 
lcvp->lu_type);
+               break;
+       }
+
+       osmo_timer_schedule(&fi->timer, vlr_timer_secs(vlr, fi->T, fi->T), 0);
+
+       return 0;
+}
+
 static const struct osmo_fsm_state lu_compl_vlr_states[] = {
        [LU_COMPL_VLR_S_INIT] = {
                .in_event_mask = S(LU_COMPL_VLR_E_START),
@@ -579,6 +617,7 @@
                                  S(LU_COMPL_VLR_S_WAIT_TMSI_CNF) |
                                  S(LU_COMPL_VLR_S_DONE),
                .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_SUB_PRES),
+               .onenter = vlr_lu_compl_fsm_reset_n,
                .action = lu_compl_vlr_wait_subscr_pres,
        },
        [LU_COMPL_VLR_S_WAIT_IMEI] = {
@@ -586,6 +625,7 @@
                                 S(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
                .out_state_mask = S(LU_COMPL_VLR_S_DONE),
                .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_IMEI),
+               .onenter = vlr_lu_compl_fsm_reset_n,
                .action = lu_compl_vlr_wait_imei,
        },
        [LU_COMPL_VLR_S_WAIT_IMEI_TMSI] = {
@@ -594,12 +634,14 @@
                .out_state_mask = S(LU_COMPL_VLR_S_DONE) |
                                  S(LU_COMPL_VLR_S_WAIT_TMSI_CNF),
                .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_IMEI_TMSI),
+               .onenter = vlr_lu_compl_fsm_reset_n,
                .action = lu_compl_vlr_wait_imei,
        },
        [LU_COMPL_VLR_S_WAIT_TMSI_CNF] = {
                .in_event_mask = S(LU_COMPL_VLR_E_NEW_TMSI_ACK),
                .out_state_mask = S(LU_COMPL_VLR_S_DONE),
                .name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_TMSI_CNF),
+               .onenter = vlr_lu_compl_fsm_reset_n,
                .action = lu_compl_vlr_wait_tmsi,
        },
        [LU_COMPL_VLR_S_DONE] = {
@@ -616,6 +658,7 @@
        .allstate_action = NULL,
        .log_subsys = DLGLOBAL,
        .event_names = lu_compl_vlr_event_names,
+       .timer_cb = lu_compl_vlr_timeout,
 };

 static inline struct lu_compl_vlr_priv *lu_compl_vlr_fi_priv(struct 
osmo_fsm_inst *fi)
@@ -711,6 +754,8 @@
        uint32_t tmsi;
        struct osmo_location_area_id old_lai;
        struct osmo_location_area_id new_lai;
+       struct osmo_routing_area_id old_rai;
+       struct osmo_routing_area_id new_rai;
        bool authentication_required;
        /* is_ciphering_to_be_attempted: true when any A5/n > 0 are enabled. 
Ciphering is allowed, always attempt to get Auth Info from
         * the HLR. */
@@ -722,6 +767,9 @@
        bool is_r99;
        bool is_utran;
        bool assign_tmsi;
+
+       /*! count times timer T timed out */
+       int N;
 };


@@ -1386,6 +1434,12 @@
        }
 }

+static void lu_fsm_reset_n(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+       struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
+       lfp->N = 0;
+}
+
 static const struct osmo_fsm_state vlr_lu_fsm_states[] = {
        [VLR_ULA_S_IDLE] = {
                .in_event_mask = S(VLR_ULA_E_UPDATE_LA),
@@ -1450,6 +1504,7 @@
                                  S(VLR_ULA_S_WAIT_HLR_UPD) |
                                  S(VLR_ULA_S_DONE),
                .name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_IMSI),
+               .onenter = lu_fsm_reset_n,
                .action = lu_fsm_wait_imsi,
        },
        [VLR_ULA_S_WAIT_HLR_CHECK_IMEI_EARLY] = {
@@ -1511,6 +1566,54 @@
                vsub->lu_fsm = NULL;
 }

+static void fsm_lu_preterm(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause 
cause)
+{
+       struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
+       uint8_t gsm48_cause;
+
+       if (vlr_is_cs(lfp->vlr))
+               return;
+
+       if (cause != OSMO_FSM_TERM_TIMEOUT)
+               return;
+
+       switch (fi->state) {
+       case VLR_ULA_S_WAIT_IMSI:
+               gsm48_cause = GSM48_REJECT_MS_IDENTITY_NOT_DERVIVABLE;
+               break;
+       case VLR_ULA_S_WAIT_AUTH:
+       default:
+               gsm48_cause = GSM48_REJECT_NETWORK_FAILURE;
+       }
+
+       lfp->vlr->ops.tx_lu_rej(lfp->msc_conn_ref, gsm48_cause, lfp->lu_type);
+}
+
+int fsm_lu_timer_cb(struct osmo_fsm_inst *fi)
+{
+       struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi);
+       struct vlr_instance *vlr = lfp->vlr;
+
+       /* only PS requires resending, CS termiante FSM */
+       if (vlr_is_cs(vlr))
+               return 1;
+
+       /* PS: we have to resend the complete message 5x times, before failing 
*/
+       if (++lfp->N >= 5)
+               return 1;
+
+       switch (fi->state) {
+       case VLR_ULA_S_WAIT_IMSI:
+               vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMSI);
+               break;
+       }
+
+       osmo_timer_schedule(&fi->timer, vlr_timer_secs(vlr, fi->T, fi->T), 0);
+
+       return 0;
+}
+
+
 static struct osmo_fsm vlr_lu_fsm = {
        .name = "vlr_lu_fsm",
        .states = vlr_lu_fsm_states,
@@ -1520,6 +1623,8 @@
        .log_subsys = DLGLOBAL,
        .event_names = fsm_lu_event_names,
        .cleanup = fsm_lu_cleanup,
+       .pre_term = fsm_lu_preterm,
+       .timer_cb = fsm_lu_timer_cb,
 };

 static inline struct lu_fsm_priv *lu_fsm_fi_priv(struct osmo_fsm_inst *fi)
@@ -1528,8 +1633,8 @@
        return (struct lu_fsm_priv*)fi->priv;
 }

-struct osmo_fsm_inst *
-vlr_loc_update(struct osmo_fsm_inst *parent,
+static struct osmo_fsm_inst *
+_vlr_loc_update(struct osmo_fsm_inst *parent,
               uint32_t parent_event_success,
               uint32_t parent_event_failure,
               void *parent_event_data,
@@ -1579,6 +1684,103 @@
        }
        fi->priv = lfp;

+       return fi;
+}
+
+struct osmo_fsm_inst *
+vlr_loc_update(struct osmo_fsm_inst *parent,
+              uint32_t parent_event_success,
+              uint32_t parent_event_failure,
+              void *parent_event_data,
+              struct vlr_instance *vlr, void *msc_conn_ref,
+              enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
+              const struct osmo_location_area_id *old_lai,
+              const struct osmo_location_area_id *new_lai,
+              bool authentication_required,
+              bool is_ciphering_to_be_attempted,
+              bool is_ciphering_required,
+              uint8_t key_seq,
+              bool is_r99, bool is_utran,
+              bool assign_tmsi)
+{
+       struct osmo_fsm_inst *fi = _vlr_loc_update(
+               parent,
+               parent_event_success,
+               parent_event_failure,
+               parent_event_data,
+               vlr, msc_conn_ref,
+               type, tmsi, imsi,
+               old_lai,
+               new_lai,
+               authentication_required,
+               is_ciphering_to_be_attempted,
+               is_ciphering_required,
+               key_seq,
+               is_r99, is_utran,
+               assign_tmsi);
+
+       if (!fi)
+               return NULL;
+
+       LOGPFSM(fi, "rev=%s net=%s%s%s\n",
+               is_r99 ? "R99" : "GSM",
+               is_utran ? "UTRAN" : "GERAN",
+               (authentication_required || is_ciphering_to_be_attempted) ?
+                   " Auth" : " (no Auth)",
+               (authentication_required || is_ciphering_to_be_attempted) ?
+                   (is_ciphering_to_be_attempted ? "+Ciph" : " (no Ciph)")
+                                                                         : "");
+
+       if (is_utran && !authentication_required)
+               LOGPFSML(fi, LOGL_ERROR,
+                        "Authentication off on UTRAN network. Good luck.\n");
+
+       osmo_fsm_inst_dispatch(fi, VLR_ULA_E_UPDATE_LA, NULL);
+
+       return fi;
+}
+
+
+struct osmo_fsm_inst *
+vlr_ra_update(struct osmo_fsm_inst *parent,
+              uint32_t parent_event_success,
+              uint32_t parent_event_failure,
+              void *parent_event_data,
+              struct vlr_instance *vlr, void *msc_conn_ref,
+              enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
+              const struct osmo_routing_area_id *old_rai,
+              const struct osmo_routing_area_id *new_rai,
+              bool authentication_required,
+              bool is_ciphering_to_be_attempted,
+              bool is_ciphering_required,
+              uint8_t key_seq,
+              bool is_r99, bool is_utran,
+              bool assign_tmsi)
+{
+       struct lu_fsm_priv *lfp;
+       struct osmo_fsm_inst *fi = _vlr_loc_update(
+           parent,
+           parent_event_success,
+           parent_event_failure,
+           parent_event_data,
+           vlr, msc_conn_ref,
+           type, tmsi, imsi,
+           &old_rai->lac,
+           &new_rai->lac,
+           authentication_required,
+           is_ciphering_to_be_attempted,
+           is_ciphering_required,
+           key_seq,
+           is_r99, is_utran,
+           assign_tmsi);
+
+       if (!fi)
+               return NULL;
+
+       lfp = fi->priv;
+       lfp->old_rai = *old_rai;
+       lfp->new_rai = *new_rai;
+
        LOGPFSM(fi, "rev=%s net=%s%s%s\n",
                is_r99 ? "R99" : "GSM",
                is_utran ? "UTRAN" : "GERAN",

--
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/38490?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: Ie9ffeb140c9d354b3a0f4822e2619f623235add0
Gerrit-Change-Number: 38490
Gerrit-PatchSet: 1
Gerrit-Owner: lynxis lazus <[email protected]>

Reply via email to