diff options
author | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2015-05-15 15:50:43 +0200 |
---|---|---|
committer | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2015-05-21 17:10:42 +0200 |
commit | 939904672961fa7e28397e27f942a7d1fff4bbdf (patch) | |
tree | f17d491b73f8c54982da96a2431b45e8d98f6000 /src | |
parent | e43460b50fc152026ab96b5095b94fbac6939ab2 (diff) |
ms: Support new and old TLLIs
According to the specification (GSM 04.08/24.008, 4.7.1.5) after a
new P-TMSI has been assigned, the old P-TMSI must be kept basically
until it has been used by both sides. Since the TLLI will be derived
from the P-TMSI, the old TLLI must also be kept until the new TLLI
has been used by both MS and SGSN.
This commit modifies the TLLI handling of GprsMs accordingly.
set_tlli() is only used with TLLIs derived from MS messages,
confirm_tlli() is used with TLLIs derived from messages received from
the SGSN. tlli() returns the value set by the MS. check_tlli()
matches each of the TLLI used by either MS or SGSN as well as the old
TLLI until it has been confirmed.
Sponsored-by: On-Waves ehf
Diffstat (limited to 'src')
-rw-r--r-- | src/gprs_bssgp_pcu.cpp | 16 | ||||
-rw-r--r-- | src/gprs_ms.cpp | 46 | ||||
-rw-r--r-- | src/gprs_ms.h | 17 | ||||
-rw-r--r-- | src/gprs_ms_storage.cpp | 4 | ||||
-rw-r--r-- | src/tbf.cpp | 25 | ||||
-rw-r--r-- | src/tbf.h | 3 | ||||
-rw-r--r-- | src/tbf_dl.cpp | 19 |
7 files changed, 94 insertions, 36 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index db271a5b..1c356670 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -118,6 +118,7 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) struct bssgp_ud_hdr *budh; uint32_t tlli; + uint32_t tlli_old = 0; uint8_t *data; uint16_t len; char imsi[16] = "000"; @@ -163,9 +164,22 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) LOGP(DBSSGP, LOGL_NOTICE, "BSSGP missing mandatory " "PDU_LIFETIME IE\n"); + /* get optional TLLI old */ + if (TLVP_PRESENT(tp, BSSGP_IE_TLLI)) + { + uint8_t tlli_len = TLVP_LEN(tp, BSSGP_IE_PDU_LIFETIME); + uint16_t *e_tlli_old = (uint16_t *) TLVP_VAL(tp, BSSGP_IE_TLLI); + if (tlli_len == 2) + tlli_old = ntohs(*e_tlli_old); + else + LOGP(DBSSGP, LOGL_NOTICE, "BSSGP invalid length of " + "TLLI (old) IE\n"); + } + LOGP(DBSSGP, LOGL_INFO, "LLC [SGSN -> PCU] = TLLI: 0x%08x IMSI: %s len: %d\n", tlli, imsi, len); - return gprs_rlcmac_dl_tbf::handle(the_pcu.bts, tlli, imsi, ms_class, delay_csec, data, len); + return gprs_rlcmac_dl_tbf::handle(the_pcu.bts, tlli, tlli_old, imsi, + ms_class, delay_csec, data, len); } int gprs_bssgp_pcu_rx_paging_ps(struct msgb *msg, struct tlv_parsed *tp) diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp index af9e834b..4c2f7cc0 100644 --- a/src/gprs_ms.cpp +++ b/src/gprs_ms.cpp @@ -58,6 +58,8 @@ GprsMs::GprsMs(uint32_t tlli) : m_ul_tbf(NULL), m_dl_tbf(NULL), m_tlli(tlli), + m_new_ul_tlli(0), + m_new_dl_tlli(0), m_is_idle(true), m_ref(0), m_list(this) @@ -185,12 +187,52 @@ void GprsMs::update_status() void GprsMs::set_tlli(uint32_t tlli) { - if (tlli == m_tlli) + if (tlli == m_tlli || tlli == m_new_ul_tlli) return; + if (tlli != m_new_dl_tlli) { + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, UL TLLI: 0x%08x -> 0x%08x, " + "not yet confirmed\n", + this->tlli(), tlli); + m_new_ul_tlli = tlli; + return; + } + LOGP(DRLCMAC, LOGL_INFO, - "Modifying MS object, TLLI: 0x%08x -> 0x%08x\n", + "Modifying MS object, TLLI: 0x%08x -> 0x%08x, " + "already confirmed partly\n", m_tlli, tlli); m_tlli = tlli; + m_new_dl_tlli = 0; + m_new_ul_tlli = 0; +} + +bool GprsMs::confirm_tlli(uint32_t tlli) +{ + if (tlli == m_tlli || tlli == m_new_dl_tlli) + return false; + + if (tlli != m_new_ul_tlli) { + /* The MS has not sent a message with the new TLLI, which may + * happen according to the spec [TODO: add reference]. */ + + LOGP(DRLCMAC, LOGL_INFO, + "The MS object cannot fully confirm an unexpected TLLI: 0x%08x, " + "partly confirmed\n", tlli); + /* Use the network's idea of TLLI as candidate, this does not + * change the result value of tlli() */ + m_new_dl_tlli = tlli; + return false; + } + + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, TLLI: 0x%08x confirmed\n", tlli); + + m_tlli = tlli; + m_new_dl_tlli = 0; + m_new_ul_tlli = 0; + + return true; } diff --git a/src/gprs_ms.h b/src/gprs_ms.h index 3a8a2e17..ac1928e7 100644 --- a/src/gprs_ms.h +++ b/src/gprs_ms.h @@ -51,8 +51,10 @@ public: gprs_rlcmac_ul_tbf *ul_tbf() const {return m_ul_tbf;} gprs_rlcmac_dl_tbf *dl_tbf() const {return m_dl_tbf;} - uint32_t tlli() const {return m_tlli;} + uint32_t tlli() const; void set_tlli(uint32_t tlli); + bool confirm_tlli(uint32_t tlli); + bool check_tlli(uint32_t tlli); void attach_tbf(gprs_rlcmac_tbf *tbf); void attach_ul_tbf(gprs_rlcmac_ul_tbf *tbf); @@ -78,7 +80,20 @@ private: gprs_rlcmac_ul_tbf *m_ul_tbf; gprs_rlcmac_dl_tbf *m_dl_tbf; uint32_t m_tlli; + uint32_t m_new_ul_tlli; + uint32_t m_new_dl_tlli; bool m_is_idle; int m_ref; LListHead<GprsMs> m_list; }; + +inline uint32_t GprsMs::tlli() const +{ + return m_new_ul_tlli ? m_new_ul_tlli : m_tlli; +} + +inline bool GprsMs::check_tlli(uint32_t tlli) +{ + return tlli != 0 && + (tlli == m_tlli || tlli == m_new_ul_tlli || tlli == m_new_dl_tlli); +} diff --git a/src/gprs_ms_storage.cpp b/src/gprs_ms_storage.cpp index 7260f1bb..4f72c86f 100644 --- a/src/gprs_ms_storage.cpp +++ b/src/gprs_ms_storage.cpp @@ -58,9 +58,9 @@ GprsMs *GprsMsStorage::get_ms(uint32_t tlli, uint32_t old_tlli, const char *imsi llist_for_each(pos, &m_list) { ms = pos->entry(); - if (tlli && ms->tlli() == tlli) + if (ms->check_tlli(tlli)) break; - if (old_tlli && ms->tlli() == old_tlli) + if (ms->check_tlli(old_tlli)) break; /* TODO: Check for IMSI */ diff --git a/src/tbf.cpp b/src/tbf.cpp index 799699ae..a3793638 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -95,8 +95,10 @@ void gprs_rlcmac_tbf::update_ms(uint32_t tlli) { if (!ms()) set_ms(bts->ms_store().get_or_create_ms(tlli)); - else + else if (direction == GPRS_RLCMAC_UL_TBF) ms()->set_tlli(tlli); + else + ms()->confirm_tlli(tlli); } gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts, @@ -814,27 +816,6 @@ void gprs_rlcmac_tbf::update_tlli(uint32_t tlli) bool changedUl = false; - /* - * During a Routing Area Update (due the assignment of a new - * P-TMSI) the tlli can change. We notice this when receiving - * a PACKET CONTROL ACK. - * When we get a TLLI change on the DL we will look if there - * is a UL TBF and change the tlli there as well. - * - * TODO: There could be multiple DL and UL TBFs and we should - * have a proper way to link all the related TBFs so we can do - * a group update. - */ - if (m_tlli_valid && direction == GPRS_RLCMAC_DL_TBF) { - gprs_rlcmac_tbf *ul_tbf; - ul_tbf = bts->ul_tbf_by_tlli(m_tlli); - - if (ul_tbf) { - ul_tbf->m_tlli = tlli; - changedUl = true; - } - } - /* update the timing advance for the new tlli */ bts->timing_advance()->update(m_tlli, tlli, ta); @@ -328,7 +328,8 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf { /* dispatch Unitdata.DL messages */ static int handle(struct gprs_rlcmac_bts *bts, - const uint32_t tlli, const char *imsi, const uint8_t ms_class, + const uint32_t tlli, const uint32_t old_tlli, + const char *imsi, const uint8_t ms_class, const uint16_t delay_csec, const uint8_t *data, const uint16_t len); int append_data(const uint8_t ms_class, diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index 5cdac5f5..b258a3c8 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -135,9 +135,10 @@ int gprs_rlcmac_dl_tbf::append_data(const uint8_t ms_class, } static struct gprs_rlcmac_dl_tbf *tbf_lookup_dl(BTS *bts, - const uint32_t tlli, const char *imsi) + const uint32_t tlli, const uint32_t tlli_old, + const char *imsi) { - GprsMs *ms = bts->ms_store().get_ms(tlli, 0, imsi); + GprsMs *ms = bts->ms_store().get_ms(tlli, tlli_old, imsi); if (!ms) return NULL; @@ -146,7 +147,8 @@ static struct gprs_rlcmac_dl_tbf *tbf_lookup_dl(BTS *bts, static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts, const char *imsi, - const uint32_t tlli, const uint8_t ms_class, + const uint32_t tlli, const uint32_t tlli_old, + const uint8_t ms_class, const uint8_t *data, const uint16_t len) { uint8_t trx, ta, ss; @@ -160,7 +162,7 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts, /* check for uplink data, so we copy our informations */ #warning "Do the same look up for IMSI, TLLI and OLD_TLLI" #warning "Refactor the below lines... into a new method" - ms = bts->bts->ms_store().get_ms(tlli, 0, imsi); + ms = bts->bts->ms_store().get_ms(tlli, tlli_old, imsi); if (ms) ul_tbf = ms->ul_tbf(); @@ -229,22 +231,25 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts, * TODO: split into unit test-able parts... */ int gprs_rlcmac_dl_tbf::handle(struct gprs_rlcmac_bts *bts, - const uint32_t tlli, const char *imsi, + const uint32_t tlli, const uint32_t tlli_old, const char *imsi, const uint8_t ms_class, const uint16_t delay_csec, const uint8_t *data, const uint16_t len) { struct gprs_rlcmac_dl_tbf *dl_tbf; /* check for existing TBF */ - dl_tbf = tbf_lookup_dl(bts->bts, tlli, imsi); + dl_tbf = tbf_lookup_dl(bts->bts, tlli, tlli_old, imsi); if (dl_tbf) { int rc = dl_tbf->append_data(ms_class, delay_csec, data, len); if (rc >= 0) dl_tbf->assign_imsi(imsi); + + if (dl_tbf->ms()) + dl_tbf->ms()->confirm_tlli(tlli); return rc; } - return tbf_new_dl_assignment(bts, imsi, tlli, ms_class, data, len); + return tbf_new_dl_assignment(bts, imsi, tlli, tlli_old, ms_class, data, len); } struct msgb *gprs_rlcmac_dl_tbf::llc_dequeue(bssgp_bvc_ctx *bctx) |