diff options
-rw-r--r-- | openbsc/include/openbsc/gprs_llc.h | 16 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_llc.c | 87 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_llc_vty.c | 22 |
3 files changed, 114 insertions, 11 deletions
diff --git a/openbsc/include/openbsc/gprs_llc.h b/openbsc/include/openbsc/gprs_llc.h index 3bdaddc4f..0ddb51804 100644 --- a/openbsc/include/openbsc/gprs_llc.h +++ b/openbsc/include/openbsc/gprs_llc.h @@ -76,6 +76,19 @@ enum gprs_llc_llme_state { GPRS_LLMS_ASSIGNED = 2, /* TLLI assigned */ }; +/* Section 8.9.9 LLC layer parameter default values */ +struct gprs_llc_params { + uint16_t iov_i_exp; + uint16_t t200_201; + uint16_t n200; + uint16_t n201_u; + uint16_t n201_i; + uint16_t mD; + uint16_t mU; + uint16_t kD; + uint16_t kU; +}; + /* Section 4.7.1: Logical Link Entity: One per DLCI (TLLI + SAPI) */ struct gprs_llc_lle { struct llist_head list; @@ -96,8 +109,9 @@ struct gprs_llc_lle { uint16_t vu_send; uint16_t vu_recv; - unsigned int n200; unsigned int retrans_ctr; + + struct gprs_llc_params params; }; #define NUM_SAPIS 16 diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c index cb581f162..54f06f926 100644 --- a/openbsc/src/gprs/gprs_llc.c +++ b/openbsc/src/gprs/gprs_llc.c @@ -36,11 +36,79 @@ #include <openbsc/gprs_llc.h> #include <openbsc/crc24.h> +/* Section 8.9.9 LLC layer parameter default values */ +static const struct gprs_llc_params llc_default_params[] = { + [1] = { + .t200_201 = 5, + .n200 = 3, + .n201_u = 400, + }, + [2] = { + .t200_201 = 5, + .n200 = 3, + .n201_u = 270, + }, + [3] = { + .iov_i_exp = 27, + .t200_201 = 5, + .n200 = 3, + .n201_u = 500, + .n201_i = 1503, + .mD = 1520, + .mU = 1520, + .kD = 16, + .kU = 16, + }, + [5] = { + .iov_i_exp = 27, + .t200_201 = 10, + .n200 = 3, + .n201_u = 500, + .n201_i = 1503, + .mD = 760, + .mU = 760, + .kD = 8, + .kU = 8, + }, + [7] = { + .t200_201 = 20, + .n200 = 3, + .n201_u = 270, + }, + [8] = { + .t200_201 = 20, + .n200 = 3, + .n201_u = 270, + }, + [9] = { + .iov_i_exp = 27, + .t200_201 = 20, + .n200 = 3, + .n201_u = 500, + .n201_i = 1503, + .mD = 380, + .mU = 380, + .kD = 4, + .kU = 4, + }, + [11] = { + .iov_i_exp = 27, + .t200_201 = 40, + .n200 = 3, + .n201_u = 500, + .n201_i = 1503, + .mD = 190, + .mU = 190, + .kD = 2, + .kU = 2, + }, +}; + LLIST_HEAD(gprs_llc_llmes); void *llc_tall_ctx; /* lookup LLC Entity based on DLCI (TLLI+SAPI tuple) */ -static struct gprs_llc_lle *lle_by_tlli_sapi(uint32_t tlli, uint32_t sapi) +static struct gprs_llc_lle *lle_by_tlli_sapi(uint32_t tlli, uint8_t sapi) { struct gprs_llc_llme *llme; @@ -51,7 +119,7 @@ static struct gprs_llc_lle *lle_by_tlli_sapi(uint32_t tlli, uint32_t sapi) return NULL; } -static void lle_init(struct gprs_llc_llme *llme, uint32_t sapi) +static void lle_init(struct gprs_llc_llme *llme, uint8_t sapi) { struct gprs_llc_lle *lle = &llme->lle[sapi]; @@ -59,8 +127,8 @@ static void lle_init(struct gprs_llc_llme *llme, uint32_t sapi) lle->sapi = sapi; lle->state = GPRS_LLES_UNASSIGNED; - /* FIXME: Initialize according to parameters from SAPI9 */ - + /* Initialize according to parameters */ + memcpy(&lle->params, &llc_default_params[sapi], sizeof(lle->params)); } static struct gprs_llc_llme *llme_alloc(uint32_t tlli) @@ -150,7 +218,7 @@ static void t200_expired(void *data) /* 8.5.1.3: Expiry of T200 */ - if (lle->retrans_ctr >= lle->n200) { + if (lle->retrans_ctr >= lle->params.n200) { /* FIXME: LLGM-STATUS-IND, LL-RELEASE-IND/CNF */ lle->state = GPRS_LLES_ASSIGNED_ADM; } @@ -174,7 +242,7 @@ static void t201_expired(void *data) { struct gprs_llc_lle *lle = data; - if (lle->retrans_ctr < lle->n200) { + if (lle->retrans_ctr < lle->params.n200) { /* FIXME: transmit apropriate supervisory frame (8.6.4.1) */ /* FIXME: set timer T201 */ lle->retrans_ctr++; @@ -248,6 +316,13 @@ int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command, llme = llme_alloc(msgb_tlli(msg)); lle = &llme->lle[sapi]; } + + if (msg->len > lle->params.n201_u) { + LOGP(DLLC, LOGL_ERROR, "Cannot Tx %u bytes (N201-U=%u)\n", + msg->len, lle->params.n201_u); + return -EFBIG; + } + /* Update LLE's (BVCI, NSEI) tuple */ lle->llme->bvci = msgb_bvci(msg); lle->llme->nsei = msgb_nsei(msg); diff --git a/openbsc/src/gprs/gprs_llc_vty.c b/openbsc/src/gprs/gprs_llc_vty.c index 6f0de046e..cb91a3a06 100644 --- a/openbsc/src/gprs/gprs_llc_vty.c +++ b/openbsc/src/gprs/gprs_llc_vty.c @@ -52,14 +52,21 @@ struct value_string gprs_llc_state_strs[] = { static void vty_dump_lle(struct vty *vty, struct gprs_llc_lle *lle) { + struct gprs_llc_params *par = &lle->params; vty_out(vty, " SAPI %2u State %s VUsend=%u, VUrecv=%u", lle->sapi, get_value_string(gprs_llc_state_strs, lle->state), lle->vu_send, lle->vu_recv); - vty_out(vty, " Vsent=%u Vack=%u Vrecv=%u, N200=%u, RetransCtr=%u%s", - lle->v_sent, lle->v_ack, lle->v_recv, lle->n200, + vty_out(vty, " Vsent=%u Vack=%u Vrecv=%u, RetransCtr=%u%s", + lle->v_sent, lle->v_ack, lle->v_recv, lle->retrans_ctr, VTY_NEWLINE); + vty_out(vty, " T200=%u, N200=%u, N201-U=%u, N201-I=%u, mD=%u, " + "mU=%u, kD=%u, kU=%u%s", par->t200_201, par->n200, + par->n201_u, par->n201_i, par->mD, par->mU, par->kD, + par->kU, VTY_NEWLINE); } +static uint8_t valid_sapis[] = { 1, 2, 3, 5, 7, 8, 9, 11 }; + static void vty_dump_llme(struct vty *vty, struct gprs_llc_llme *llme) { unsigned int i; @@ -67,8 +74,15 @@ static void vty_dump_llme(struct vty *vty, struct gprs_llc_llme *llme) vty_out(vty, "TLLI %08x (Old TLLI %08x) BVCI=%u NSEI=%u: State %s%s", llme->tlli, llme->old_tlli, llme->bvci, llme->nsei, get_value_string(gprs_llc_state_strs, llme->state), VTY_NEWLINE); - for (i = 0; i < ARRAY_SIZE(llme->lle); i++) { - struct gprs_llc_lle *lle = &llme->lle[i]; + + for (i = 0; i < ARRAY_SIZE(valid_sapis); i++) { + struct gprs_llc_lle *lle; + uint8_t sapi = valid_sapis[i]; + + if (sapi >= ARRAY_SIZE(llme->lle)) + continue; + + lle = &llme->lle[sapi]; vty_dump_lle(vty, lle); } } |