diff options
Diffstat (limited to 'src/gprs/gprs_llc.c')
-rw-r--r-- | src/gprs/gprs_llc.c | 86 |
1 files changed, 66 insertions, 20 deletions
diff --git a/src/gprs/gprs_llc.c b/src/gprs/gprs_llc.c index 7991f4c1e..e8963b315 100644 --- a/src/gprs/gprs_llc.c +++ b/src/gprs/gprs_llc.c @@ -22,10 +22,10 @@ #include <errno.h> #include <stdint.h> -#include <osmocore/msgb.h> -#include <osmocore/linuxlist.h> -#include <osmocore/timer.h> -#include <osmocore/talloc.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/talloc.h> #include <openbsc/gsm_data.h> #include <openbsc/debug.h> @@ -340,7 +340,7 @@ int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command, struct gprs_llc_llme *llme; LOGP(DLLC, LOGL_ERROR, "LLC TX: unknown TLLI 0x%08x, " "creating LLME on the fly\n", msgb_tlli(msg)); - llme = llme_alloc(msgb_tlli(msg)); + llme = llme_alloc(tlli_foreign2local(msgb_tlli(msg))); lle = &llme->lle[sapi]; } @@ -350,6 +350,12 @@ int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command, return -EFBIG; } + if ((sapi != GPRS_SAPI_GMM) && lle->llme->suspended) { + LOGP(DLLC, LOGL_DEBUG, "LLC TX: suspended TLLI 0x08x, " + "dropping UI frame\n", msgb_tlli(msg)); + return 0; + } + /* Update LLE's (BVCI, NSEI) tuple */ lle->llme->bvci = msgb_bvci(msg); lle->llme->nsei = msgb_nsei(msg); @@ -476,17 +482,21 @@ static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph, } break; case GPRS_LLC_UI: - if (gph->seq_tx < lle->vu_recv) { - LOGP(DLLC, LOGL_NOTICE, "TLLI=%08x dropping UI, vurecv %u <= %u\n", - lle->llme ? lle->llme->tlli : -1, - gph->seq_tx, lle->vu_recv); - return -EIO; - } - /* Increment the sequence number that we expect in the next frame */ - lle->vu_recv = (gph->seq_tx + 1) % 512; - /* Increment Overflow Counter */ - if ((gph->seq_tx + 1) / 512) - lle->oc_ui_recv += 512; + { + int delta = (lle->vu_recv - gph->seq_tx) & 0x1ff; + if (0 < delta && delta < 32) { + LOGP(DLLC, LOGL_NOTICE, "TLLI=%08x dropping UI, vurecv %u <= %u\n", + lle->llme ? lle->llme->tlli : -1, + gph->seq_tx, lle->vu_recv); + return -EIO; + } + /* Increment the sequence number that we expect in the next frame */ + lle->vu_recv = (gph->seq_tx + 1) & 0x1ff; + /* Increment Overflow Counter */ + if (lle->vu_recv == 0) { + lle->oc_ui_recv += 512; + } + } break; } @@ -808,12 +818,12 @@ int gprs_llgmm_assign(struct gprs_llc_llme *llme, * received from peer. */ if (llme->old_tlli != 0xffffffff) { llme->old_tlli = 0xffffffff; - llme->tlli = new_tlli; + llme->tlli = tlli_foreign2local(new_tlli); } else { /* If TLLI old == 0xffffffff was assigned to LLME, then this is * TLLI assignmemt according to 8.3.1 */ llme->old_tlli = 0xffffffff; - llme->tlli = new_tlli; + llme->tlli = tlli_foreign2local(new_tlli); llme->state = GPRS_LLMS_ASSIGNED; /* 8.5.3.1 For all LLE's */ for (i = 0; i < ARRAY_SIZE(llme->lle); i++) { @@ -828,8 +838,8 @@ int gprs_llgmm_assign(struct gprs_llc_llme *llme, /* TLLI Change 8.3.2 */ /* Both TLLI Old and TLLI New are assigned; use New when * (re)transmitting. Accept toth Old and New on Rx */ - llme->old_tlli = llme->tlli; - llme->tlli = new_tlli; + llme->old_tlli = tlli_foreign2local(old_tlli); + llme->tlli = tlli_foreign2local(new_tlli); llme->state = GPRS_LLMS_ASSIGNED; } else if (old_tlli != 0xffffffff && new_tlli == 0xffffffff) { /* TLLI Unassignment 8.3.3) */ @@ -846,6 +856,42 @@ int gprs_llgmm_assign(struct gprs_llc_llme *llme, return 0; } +int gprs_llgmm_suspend(struct gprs_llc_llme* llme) +{ + llme->suspended = 1; + return 0; +} + +int gprs_llgmm_resume(struct gprs_llc_llme* llme) +{ + llme->suspended = 0; + return 0; +} + +void gprs_llgmm_reset_state(struct gprs_llc_llme *llme) +{ + unsigned int i; + + if (llme == 0) + { + LOGP(DLLC, LOGL_ERROR, "LLC TX: trying to reset LLC states " + "but passed null llme by gmm\n"); + return; + } + + LOGP(DLLC, LOGL_NOTICE, "LLC RX: reset state variable for TLLI 0x%08x", + llme->tlli); + /* 8.5.3.1 For all LLE's */ + for (i = 0; i < ARRAY_SIZE(llme->lle); i++) { + struct gprs_llc_lle *l = &llme->lle[i]; + l->vu_recv = 0; /* lets not mess with send state variable now */ + /* l->vu_send = l->vu_recv = 0; */ + l->retrans_ctr = 0; + l->state = GPRS_LLES_ASSIGNED_ADM; + /* FIXME Set parameters according to table 9 */ + } +} + int gprs_llc_init(const char *cipher_plugin_path) { return gprs_cipher_load(cipher_plugin_path); |