aboutsummaryrefslogtreecommitdiffstats
path: root/src/gprs/gprs_llc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gprs/gprs_llc.c')
-rw-r--r--src/gprs/gprs_llc.c86
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);