pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/31049 )
Change subject: llc: Initial support for GRR-UNITDATA.ind/req ......................................................................
llc: Initial support for GRR-UNITDATA.ind/req
This allows forwarding GRR-UNITDATA.ind/req up & down the stack, to be on pair with the BSSGP LLC SAP.
Change-Id: I6a4454b4aa2c96e1f4ce7e2a5d5aba8ec1cf3f60 --- M include/osmocom/gprs/llc/llc_prim.h M include/osmocom/gprs/llc/llc_private.h M src/llc/llc.c M src/llc/llc_bssgp.c M src/llc/llc_grr.c M tests/llc/llc_prim_test.c M tests/llc/llc_prim_test.err M tests/llc/llc_prim_test.ok 8 files changed, 316 insertions(+), 155 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-gprs refs/changes/49/31049/1
diff --git a/include/osmocom/gprs/llc/llc_prim.h b/include/osmocom/gprs/llc/llc_prim.h index 23b41cf..7a3991b 100644 --- a/include/osmocom/gprs/llc/llc_prim.h +++ b/include/osmocom/gprs/llc/llc_prim.h @@ -204,13 +204,20 @@ size_t ll_pdu_len; /* Specific fields */ union { - /* OSMO_GPRS_LLC_GRR_[UNIT]DATA | Req */ + /* OSMO_GPRS_LLC_GRR_DATA | Req */ struct { - uint8_t qos_params[3]; - uint8_t radio_prio; - uint8_t cause; /* only for OSMO_GPRS_LLC_GRR_UNITDATA | Req */ uint8_t sapi; + uint8_t radio_prio; + uint8_t qos_params[3]; + } data_req; + /* OSMO_GPRS_LLC_GRR_UNITDATA| Req */ + struct { + uint8_t sapi; + uint8_t radio_prio; + uint8_t qos_params[3]; + uint8_t cause; + } unitdata_req; }; };
@@ -286,3 +293,7 @@ /* Alloc primitive for BSSGP SAP: */ struct osmo_gprs_llc_prim *osmo_gprs_llc_prim_alloc_bssgp_ul_unitdata_ind( uint32_t tlli, uint8_t *ll_pdu, size_t ll_pdu_len); + +/* Alloc primitive for GRR SAP: */ +struct osmo_gprs_llc_prim *osmo_gprs_llc_prim_alloc_grr_unitdata_ind( + uint32_t tlli, uint8_t *ll_pdu, size_t ll_pdu_len); \ No newline at end of file diff --git a/include/osmocom/gprs/llc/llc_private.h b/include/osmocom/gprs/llc/llc_private.h index 4d44b74..1db33b6 100644 --- a/include/osmocom/gprs/llc/llc_private.h +++ b/include/osmocom/gprs/llc/llc_private.h @@ -282,6 +282,8 @@
/* llc_grr.c */ int gprs_llc_prim_lower_up_grr(struct osmo_gprs_llc_prim *llc_prim); +struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_grr_unitdata_req( + uint32_t tlli, uint8_t *ll_pdu, size_t ll_pdu_len);
/* llc_ll.c */ int gprs_llc_prim_ll_upper_down(struct osmo_gprs_llc_prim *llc_prim); @@ -307,7 +309,8 @@ struct gprs_llc_lle *gprs_llc_find_lle_by_tlli_sapi(uint32_t tlli, uint8_t sapi); struct gprs_llc_lle *gprs_llc_lle_for_rx_by_tlli_sapi(const uint32_t tlli, uint8_t sapi, enum gprs_llc_frame_func cmd); -int gprs_llc_lle_hdr_rx(struct gprs_llc_lle *lle, struct gprs_llc_pdu_decoded *pdu_dec); +int gprs_llc_lle_rx_unitdata_ind(struct gprs_llc_lle *lle, uint8_t *ll_pdu, size_t ll_pdu_len, + struct gprs_llc_pdu_decoded *pdu_dec); void gprs_llc_llme_free(struct gprs_llc_llme *llme); int gprs_llc_lle_tx_xid(const struct gprs_llc_lle *lle, uint8_t *xid_payload, unsigned int xid_payload_len, bool is_cmd); int gprs_llc_lle_tx_xid_req(struct gprs_llc_lle *lle, uint8_t *l3par, unsigned int l3par_len); diff --git a/src/llc/llc.c b/src/llc/llc.c index 1f52851..11dad39 100644 --- a/src/llc/llc.c +++ b/src/llc/llc.c @@ -309,7 +309,10 @@ /* TODO: we are probably missing the ciphering enc part, see osmo-sgsn apply_gea() */
/* LLC payload is put directly below: */ - llc_prim = gprs_llc_prim_alloc_bssgp_dl_unitdata_req(lle->llme->tlli, NULL, 4096 - sizeof(llc_prim)); + if (g_ctx->location == OSMO_GPRS_LLC_LOCATION_SGSN) + llc_prim = gprs_llc_prim_alloc_bssgp_dl_unitdata_req(lle->llme->tlli, NULL, 4096 - sizeof(llc_prim)); + else + llc_prim = gprs_llc_prim_alloc_grr_unitdata_req(lle->llme->tlli, NULL, 4096 - sizeof(llc_prim)); msg = llc_prim->oph.msg; msg->l3h = msg->tail;
@@ -319,8 +322,15 @@ msgb_free(msg); return rc; } - llc_prim->bssgp.ll_pdu = msgb_l3(msg); - llc_prim->bssgp.ll_pdu_len = msgb_l3len(msg); + + if (g_ctx->location == OSMO_GPRS_LLC_LOCATION_SGSN) { + llc_prim->bssgp.ll_pdu = msgb_l3(msg); + llc_prim->bssgp.ll_pdu_len = msgb_l3len(msg); + } else { + llc_prim->grr.ll_pdu = msgb_l3(msg); + llc_prim->grr.ll_pdu_len = msgb_l3len(msg); + llc_prim->grr.unitdata_req.sapi = lle->sapi; + }
/* Increment V(U) */ lle->vu_send = (lle->vu_send + 1) % 512; @@ -328,7 +338,7 @@ if ((lle->vu_send + 1) / 512) lle->oc_ui_send += 512;
- /* Send BSSGP-DL-UNITDATA.req */ + /* Send BSSGP-DL-UNITDATA.req (SGSN) / GRR-UNITDATA.req (MS) */ rc = gprs_llc_prim_call_down_cb(llc_prim); return rc; } @@ -593,7 +603,7 @@ }
/* Receive and process decoded LLC PDU from lower layer (GRR/BSSGP): */ -int gprs_llc_lle_hdr_rx(struct gprs_llc_lle *lle, struct gprs_llc_pdu_decoded *pdu_dec) +static int gprs_llc_lle_hdr_rx(struct gprs_llc_lle *lle, struct gprs_llc_pdu_decoded *pdu_dec) { const char *llc_pdu_name = gprs_llc_pdu_hdr_dump(pdu_dec);
@@ -649,3 +659,129 @@
return 0; } + +/* encrypt information field + FCS, if needed! */ +static int apply_gea(const struct gprs_llc_lle *lle, uint16_t crypt_len, uint16_t nu, + uint32_t oc, uint8_t sapi, uint8_t *fcs, uint8_t *data) +{ + uint8_t cipher_out[GSM0464_CIPH_MAX_BLOCK]; + + if (lle->llme->algo == GPRS_ALGO_GEA0) + return -EINVAL; + + /* Compute the 'Input' Paraemeter */ + uint32_t fcs_calc, iv = gprs_cipher_gen_input_ui(lle->llme->iov_ui, sapi, + nu, oc); + /* Compute gamma that we need to XOR with the data */ + int r = gprs_cipher_run(cipher_out, crypt_len, lle->llme->algo, + lle->llme->kc, iv, + fcs ? GPRS_CIPH_SGSN2MS : GPRS_CIPH_MS2SGSN); + if (r < 0) { + LOGLLC(LOGL_ERROR, "Error producing %s gamma for UI " + "frame: %d\n", get_value_string(gprs_cipher_names, + lle->llme->algo), r); + return -ENOMSG; + } + + if (fcs) { + /* Mark frame as encrypted and update FCS */ + data[2] |= 0x02; + fcs_calc = gprs_llc_fcs(data, fcs - data); + fcs[0] = fcs_calc & 0xff; + fcs[1] = (fcs_calc >> 8) & 0xff; + fcs[2] = (fcs_calc >> 16) & 0xff; + data += 3; + } + + /* XOR the cipher output with the data */ + for (r = 0; r < crypt_len; r++) + *(data + r) ^= cipher_out[r]; + + return 0; +} + +/* Shared upper part handling of BSSGP-UNITDATA.ind and GRR-UNITDATA.ind */ +int gprs_llc_lle_rx_unitdata_ind(struct gprs_llc_lle *lle, uint8_t *ll_pdu, size_t ll_pdu_len, struct gprs_llc_pdu_decoded *pdu_dec) +{ + struct osmo_gprs_llc_prim *llc_prim_tx; + bool drop_cipherable = false; + int rc; + + /* reset age computation */ + lle->llme->age_timestamp = GPRS_LLME_RESET_AGE; + + /* decrypt information field + FCS, if needed! */ + if (pdu_dec->flags & OSMO_GPRS_LLC_PDU_F_ENC_MODE) { + if (lle->llme->algo != GPRS_ALGO_GEA0) { + rc = apply_gea(lle, pdu_dec->data_len + 3, pdu_dec->seq_tx, + lle->oc_ui_recv, lle->sapi, NULL, + (uint8_t *)pdu_dec->data); /*TODO: either copy buffer or remove "const" from pdu_dec field "data" */ + if (rc < 0) + return rc; + pdu_dec->fcs = *(pdu_dec->data + pdu_dec->data_len); + pdu_dec->fcs |= *(pdu_dec->data + pdu_dec->data_len + 1) << 8; + pdu_dec->fcs |= *(pdu_dec->data + pdu_dec->data_len + 2) << 16; + } else { + LOGLLME(lle->llme, LOGL_NOTICE, "encrypted frame for LLC that " + "has no KC/Algo! Dropping.\n"); + return 0; + } + } else { + if (lle->llme->algo != GPRS_ALGO_GEA0 && + lle->llme->cksn != GSM_KEY_SEQ_INVAL) + drop_cipherable = true; + } + + /* We have to do the FCS check _after_ decryption */ + uint16_t crc_length = ll_pdu_len - CRC24_LENGTH; + if (~pdu_dec->flags & OSMO_GPRS_LLC_PDU_F_PROT_MODE) + crc_length = OSMO_MIN(crc_length, UI_HDR_LEN + N202); + if (pdu_dec->fcs != gprs_llc_fcs(ll_pdu, crc_length)) { + LOGLLE(lle, LOGL_INFO, "Dropping frame with invalid FCS\n"); + return -EIO; + } + + /* Receive and Process the actual LLC frame */ + rc = gprs_llc_lle_hdr_rx(lle, pdu_dec); + if (rc < 0) + return rc; + + /* pdu_dec->data is only set when we need to send LL_[UNIT]DATA_IND up */ + if (pdu_dec->func == OSMO_GPRS_LLC_FUNC_UI && pdu_dec->data && pdu_dec->data_len) { + switch (pdu_dec->sapi) { + case OSMO_GPRS_LLC_SAPI_GMM: + /* send LL-UNITDATA-IND to GMM */ + llc_prim_tx = gprs_llc_prim_alloc_ll_unitdata_ind(lle->llme->tlli, + pdu_dec->sapi, + pdu_dec->data, + pdu_dec->data_len); + llc_prim_tx->ll.unitdata_ind.apply_gea = !drop_cipherable; /* TODO: is this correct? */ + llc_prim_tx->ll.unitdata_ind.apply_gia = false; /* TODO: how to set this? */ + gprs_llc_prim_call_up_cb(llc_prim_tx); + break; + case OSMO_GPRS_LLC_SAPI_SNDCP3: + case OSMO_GPRS_LLC_SAPI_SNDCP5: + case OSMO_GPRS_LLC_SAPI_SNDCP9: + case OSMO_GPRS_LLC_SAPI_SNDCP11: + /* send LL_DATA_IND/LL_UNITDATA_IND to SNDCP */ + llc_prim_tx = gprs_llc_prim_alloc_ll_unitdata_ind(lle->llme->tlli, + pdu_dec->sapi, + pdu_dec->data, + pdu_dec->data_len); + llc_prim_tx->ll.unitdata_ind.apply_gea = !drop_cipherable; /* TODO: is this correct? */ + llc_prim_tx->ll.unitdata_ind.apply_gia = false; /* TODO: how to set this? */ + gprs_llc_prim_call_up_cb(llc_prim_tx); + break; + case OSMO_GPRS_LLC_SAPI_SMS: + /* FIXME */ + case OSMO_GPRS_LLC_SAPI_TOM2: + case OSMO_GPRS_LLC_SAPI_TOM8: + /* FIXME: send LL_DATA_IND/LL_UNITDATA_IND to TOM */ + default: + LOGLLC(LOGL_NOTICE, "Unsupported SAPI %u\n", pdu_dec->sapi); + rc = -EINVAL; + break; + } + } + return rc; +} \ No newline at end of file diff --git a/src/llc/llc_bssgp.c b/src/llc/llc_bssgp.c index 48d4cde..a6fd308 100644 --- a/src/llc/llc_bssgp.c +++ b/src/llc/llc_bssgp.c @@ -78,58 +78,14 @@ * Handling from lower layers: ********************************/
-/* encrypt information field + FCS, if needed! */ -static int apply_gea(const struct gprs_llc_lle *lle, uint16_t crypt_len, uint16_t nu, - uint32_t oc, uint8_t sapi, uint8_t *fcs, uint8_t *data) -{ - uint8_t cipher_out[GSM0464_CIPH_MAX_BLOCK]; - - if (lle->llme->algo == GPRS_ALGO_GEA0) - return -EINVAL; - - /* Compute the 'Input' Paraemeter */ - uint32_t fcs_calc, iv = gprs_cipher_gen_input_ui(lle->llme->iov_ui, sapi, - nu, oc); - /* Compute gamma that we need to XOR with the data */ - int r = gprs_cipher_run(cipher_out, crypt_len, lle->llme->algo, - lle->llme->kc, iv, - fcs ? GPRS_CIPH_SGSN2MS : GPRS_CIPH_MS2SGSN); - if (r < 0) { - LOGLLC(LOGL_ERROR, "Error producing %s gamma for UI " - "frame: %d\n", get_value_string(gprs_cipher_names, - lle->llme->algo), r); - return -ENOMSG; - } - - if (fcs) { - /* Mark frame as encrypted and update FCS */ - data[2] |= 0x02; - fcs_calc = gprs_llc_fcs(data, fcs - data); - fcs[0] = fcs_calc & 0xff; - fcs[1] = (fcs_calc >> 8) & 0xff; - fcs[2] = (fcs_calc >> 16) & 0xff; - data += 3; - } - - /* XOR the cipher output with the data */ - for (r = 0; r < crypt_len; r++) - *(data + r) ^= cipher_out[r]; - - return 0; -} - - static int gprs_llc_prim_handle_bssgp_ul_unitdata_ind(struct osmo_gprs_llc_prim *llc_prim) { int rc; - struct gprs_llc_hdr *lh = (struct gprs_llc_hdr *) llc_prim->bssgp.ll_pdu; struct gprs_llc_pdu_decoded pdu_dec = {0}; const char *llc_pdu_name = NULL; struct gprs_llc_lle *lle = NULL; - bool drop_cipherable = false; - struct osmo_gprs_llc_prim *llc_prim_tx;
- rc = gprs_llc_pdu_decode(&pdu_dec, (uint8_t *)lh, llc_prim->bssgp.ll_pdu_len); + rc = gprs_llc_pdu_decode(&pdu_dec, llc_prim->bssgp.ll_pdu, llc_prim->bssgp.ll_pdu_len); if (rc < 0) { LOGLLC(LOGL_ERROR, "%s: Error parsing LLC header\n", osmo_gprs_llc_prim_name(llc_prim)); return rc; @@ -166,82 +122,7 @@ } return 0; } - /* reset age computation */ - lle->llme->age_timestamp = GPRS_LLME_RESET_AGE; - - /* decrypt information field + FCS, if needed! */ - if (pdu_dec.flags & OSMO_GPRS_LLC_PDU_F_ENC_MODE) { - if (lle->llme->algo != GPRS_ALGO_GEA0) { - rc = apply_gea(lle, pdu_dec.data_len + 3, pdu_dec.seq_tx, - lle->oc_ui_recv, lle->sapi, NULL, - (uint8_t *)pdu_dec.data); /*TODO: either copy buffer or remove "const" from pdu_dec field "data" */ - if (rc < 0) - return rc; - pdu_dec.fcs = *(pdu_dec.data + pdu_dec.data_len); - pdu_dec.fcs |= *(pdu_dec.data + pdu_dec.data_len + 1) << 8; - pdu_dec.fcs |= *(pdu_dec.data + pdu_dec.data_len + 2) << 16; - } else { - LOGLLME(lle->llme, LOGL_NOTICE, "encrypted frame for LLC that " - "has no KC/Algo! Dropping.\n"); - return 0; - } - } else { - if (lle->llme->algo != GPRS_ALGO_GEA0 && - lle->llme->cksn != GSM_KEY_SEQ_INVAL) - drop_cipherable = true; - } - - /* We have to do the FCS check _after_ decryption */ - uint16_t crc_length = llc_prim->bssgp.ll_pdu_len - CRC24_LENGTH; - if (~pdu_dec.flags & OSMO_GPRS_LLC_PDU_F_PROT_MODE) - crc_length = OSMO_MIN(crc_length, UI_HDR_LEN + N202); - if (pdu_dec.fcs != gprs_llc_fcs((uint8_t *)lh, crc_length)) { - LOGLLE(lle, LOGL_INFO, "Dropping frame with invalid FCS\n"); - return -EIO; - } - - /* Receive and Process the actual LLC frame */ - rc = gprs_llc_lle_hdr_rx(lle, &pdu_dec); - if (rc < 0) - return rc; - - /* pdu_dec.data is only set when we need to send LL_[UNIT]DATA_IND up */ - if (pdu_dec.func == OSMO_GPRS_LLC_FUNC_UI && pdu_dec.data && pdu_dec.data_len) { - switch (pdu_dec.sapi) { - case OSMO_GPRS_LLC_SAPI_GMM: - /* send LL-UNITDATA-IND to GMM */ - llc_prim_tx = gprs_llc_prim_alloc_ll_unitdata_ind(lle->llme->tlli, - pdu_dec.sapi, - pdu_dec.data, - pdu_dec.data_len); - llc_prim_tx->ll.unitdata_ind.apply_gea = !drop_cipherable; /* TODO: is this correct? */ - llc_prim_tx->ll.unitdata_ind.apply_gia = false; /* TODO: how to set this? */ - gprs_llc_prim_call_up_cb(llc_prim_tx); - break; - case OSMO_GPRS_LLC_SAPI_SNDCP3: - case OSMO_GPRS_LLC_SAPI_SNDCP5: - case OSMO_GPRS_LLC_SAPI_SNDCP9: - case OSMO_GPRS_LLC_SAPI_SNDCP11: - /* send LL_DATA_IND/LL_UNITDATA_IND to SNDCP */ - llc_prim_tx = gprs_llc_prim_alloc_ll_unitdata_ind(lle->llme->tlli, - pdu_dec.sapi, - pdu_dec.data, - pdu_dec.data_len); - llc_prim_tx->ll.unitdata_ind.apply_gea = !drop_cipherable; /* TODO: is this correct? */ - llc_prim_tx->ll.unitdata_ind.apply_gia = false; /* TODO: how to set this? */ - gprs_llc_prim_call_up_cb(llc_prim_tx); - break; - case OSMO_GPRS_LLC_SAPI_SMS: - /* FIXME */ - case OSMO_GPRS_LLC_SAPI_TOM2: - case OSMO_GPRS_LLC_SAPI_TOM8: - /* FIXME: send LL_DATA_IND/LL_UNITDATA_IND to TOM */ - default: - LOGLLC(LOGL_NOTICE, "Unsupported SAPI %u\n", pdu_dec.sapi); - rc = -EINVAL; - break; - } - } + rc = gprs_llc_lle_rx_unitdata_ind(lle, llc_prim->bssgp.ll_pdu, llc_prim->bssgp.ll_pdu_len, &pdu_dec);
return rc; } diff --git a/src/llc/llc_grr.c b/src/llc/llc_grr.c index 8486a53..e6d1cf7 100644 --- a/src/llc/llc_grr.c +++ b/src/llc/llc_grr.c @@ -1,6 +1,6 @@ -/* GPRS LLC LLGM SAP as per 3GPP TS 44.064 7.2.3 */ +/* GPRS LLC GRR SAP as per 3GPP TS 44.064 7.2.3, 3GPP TS 24.007 */ /* - * (C) 2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de + * (C) 2022-2023 by sysmocom - s.f.m.c. GmbH info@sysmocom.de * * All Rights Reserved * @@ -38,6 +38,42 @@ { 0, NULL } };
+/******************************** + * Primitive allocation: + ********************************/ + +static inline struct osmo_gprs_llc_prim *llc_prim_grr_alloc(enum osmo_gprs_llc_grr_prim_type type, + enum osmo_prim_operation operation, + unsigned int l3_len) +{ + return gprs_llc_prim_alloc(OSMO_GPRS_LLC_SAP_GRR, type, operation, l3_len); +} + +/* 7.2.3.2 GRR-UNITDATA.ind (MS):*/ +struct osmo_gprs_llc_prim *osmo_gprs_llc_prim_alloc_grr_unitdata_ind( + uint32_t tlli, uint8_t *ll_pdu, + size_t ll_pdu_len) +{ + struct osmo_gprs_llc_prim *llc_prim; + llc_prim = llc_prim_grr_alloc(OSMO_GPRS_LLC_GRR_UNITDATA, PRIM_OP_INDICATION, ll_pdu_len); + llc_prim->grr.tlli = tlli; + llc_prim->grr.ll_pdu = ll_pdu; + llc_prim->grr.ll_pdu_len = ll_pdu_len; + return llc_prim; +} + +/* 7.2.3.2 GRR-UL-UNITDATA.req (MS):*/ +struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_grr_unitdata_req( + uint32_t tlli, uint8_t *ll_pdu, size_t ll_pdu_len) +{ + struct osmo_gprs_llc_prim *llc_prim; + llc_prim = llc_prim_grr_alloc(OSMO_GPRS_LLC_GRR_UNITDATA, PRIM_OP_REQUEST, ll_pdu_len); + llc_prim->grr.tlli = tlli; + llc_prim->grr.ll_pdu = ll_pdu; + llc_prim->grr.ll_pdu_len = ll_pdu_len; + return llc_prim; +} + static int llc_prim_handle_grr_data_ind(struct osmo_gprs_llc_prim *llc_prim) { int rc = gprs_llc_prim_handle_unsupported(llc_prim); @@ -46,7 +82,50 @@
static int llc_prim_handle_grr_unitdata_ind(struct osmo_gprs_llc_prim *llc_prim) { - int rc = gprs_llc_prim_handle_unsupported(llc_prim); + int rc; + struct gprs_llc_pdu_decoded pdu_dec = {0}; + const char *llc_pdu_name = NULL; + struct gprs_llc_lle *lle = NULL; + + rc = gprs_llc_pdu_decode(&pdu_dec, llc_prim->grr.ll_pdu, llc_prim->grr.ll_pdu_len); + if (rc < 0) { + LOGLLC(LOGL_ERROR, "%s: Error parsing LLC header\n", osmo_gprs_llc_prim_name(llc_prim)); + return rc; + } + llc_pdu_name = gprs_llc_pdu_hdr_dump(&pdu_dec); + + LOGLLC(LOGL_DEBUG, "Rx %s: %s\n", osmo_gprs_llc_prim_name(llc_prim), llc_pdu_name); + + switch (gprs_tlli_type(llc_prim->bssgp.tlli)) { + case TLLI_LOCAL: + case TLLI_FOREIGN: + case TLLI_RANDOM: + case TLLI_AUXILIARY: + break; + default: + LOGLLC(LOGL_ERROR, "%s: Discarding frame with strange TLLI type\n", llc_pdu_name); + return -EINVAL; + } + + lle = gprs_llc_lle_for_rx_by_tlli_sapi(llc_prim->grr.tlli, pdu_dec.sapi, pdu_dec.func); + if (!lle) { + switch (pdu_dec.sapi) { + case OSMO_GPRS_LLC_SAPI_SNDCP3: + case OSMO_GPRS_LLC_SAPI_SNDCP5: + case OSMO_GPRS_LLC_SAPI_SNDCP9: + case OSMO_GPRS_LLC_SAPI_SNDCP11: +#if 0 +/* TODO: probaby send some primitive to the upper layers (GMM) */ + /* Ask an upper layer for help. */ + return gsm0408_gprs_force_reattach_oldmsg(msg, NULL); +#endif + default: + break; + } + return 0; + } + rc = gprs_llc_lle_rx_unitdata_ind(lle, llc_prim->grr.ll_pdu, llc_prim->grr.ll_pdu_len, &pdu_dec); + return rc; }
diff --git a/tests/llc/llc_prim_test.c b/tests/llc/llc_prim_test.c index ab3bf65..c7c6e3c 100644 --- a/tests/llc/llc_prim_test.c +++ b/tests/llc/llc_prim_test.c @@ -65,7 +65,8 @@
switch (llc_prim->oph.sap) { case OSMO_GPRS_LLC_SAP_GRR: - printf("%s(): Rx %s l3=[%s]\n", __func__, pdu_name, osmo_hexdump(llc_prim->grr.ll_pdu, llc_prim->grr.ll_pdu_len)); + printf("%s(): Rx %s l3=[%s]\n", __func__, pdu_name, + osmo_hexdump(llc_prim->grr.ll_pdu, llc_prim->grr.ll_pdu_len)); break; case OSMO_GPRS_LLC_SAP_BSSGP: printf("%s(): Rx %s TLLI=0x%08x l3=[%s]\n", __func__, pdu_name, @@ -78,27 +79,40 @@ return 0; }
-static void test_llc_prim_ms(void) -{ - //struct osmo_gprs_llc_prim *llc_prim; - //uint32_t tlli = 0x11223344; - int rc; +/* +GSM A-I/F DTAP - Attach Request + Protocol Discriminator: GPRS mobility management messages (8) + DTAP GPRS Mobility Management Message Type: Attach Request (0x01) + MS Network Capability + Length: 2 + 1... .... = GEA/1: Encryption algorithm available + .1.. .... = SM capabilities via dedicated channels: Mobile station supports mobile terminated point to point SMS via dedicated signalling channels + ..1. .... = SM capabilities via GPRS channels: Mobile station supports mobile terminated point to point SMS via GPRS packet data channels + ...0 .... = UCS2 support: The ME has a preference for the default alphabet (defined in 3GPP TS 23.038 [8b]) over UCS2 + .... 01.. = SS Screening Indicator: capability of handling of ellipsis notation and phase 2 error handling (0x1) + .... ..0. = SoLSA Capability: The ME does not support SoLSA + .... ...1 = Revision level indicator: Used by a mobile station supporting R99 or later versions of the protocol + 1... .... = PFC feature mode: Mobile station does support BSS packet flow procedures + .110 000. = Extended GEA bits: 0x30 + .... ...0 = LCS VA capability: LCS value added location request notification capability not supported + Attach Type + Ciphering Key Sequence Number + DRX Parameter + Mobile Identity - TMSI/P-TMSI (0xf43cec71) + Routing Area Identification - Old routing area identification - RAI: 234-70-5-0 + MS Radio Access Capability + GPRS Timer - Ready Timer + Element ID: 0x17 + GPRS Timer: 10 sec + 000. .... = Unit: value is incremented in multiples of 2 seconds (0) + ...0 0101 = Timer value: 5
- printf("==== %s() [start] ====\n", __func__); - - rc = osmo_gprs_llc_init(OSMO_GPRS_LLC_LOCATION_MS, NULL); - OSMO_ASSERT(rc == 0); - - osmo_gprs_llc_prim_set_up_cb(test_llc_prim_up_cb, NULL); - osmo_gprs_llc_prim_set_down_cb(test_llc_prim_down_cb, NULL); - - //llc_prim = osmo_gprs_llc_prim_alloc_llgm_reset_req(tlli); - //OSMO_ASSERT(llc_prim); - //rc = osmo_gprs_llc_prim_upper_down(llc_prim); - //OSMO_ASSERT(rc == 0); - - printf("==== %s() [end] ====\n", __func__); -} +*/ +static uint8_t pdu_gmmm_attach_req[] = { + 0x08, 0x01, 0x02, 0xe5, 0xe0, 0x01, 0x0a, 0x00, 0x05, 0xf4, 0xf4, 0x3c, 0xec, 0x71, 0x32, 0xf4, + 0x07, 0x00, 0x05, 0x00, 0x17, 0x19, 0x33, 0x43, 0x2b, 0x37, 0x15, 0x9e, 0xf9, 0x88, 0x79, 0xcb, + 0xa2, 0x8c, 0x66, 0x21, 0xe7, 0x26, 0x88, 0xb1, 0x98, 0x87, 0x9c, 0x00, 0x17, 0x05 +};
/** MS-SGSN LLC (Mobile Station - Serving GPRS Support Node Logical Link Control) SAPI: GPRS Mobility Management @@ -139,6 +153,36 @@ */ static uint8_t pdu_gmm_id_req[] = { 0x08, 0x15, 0x02 };
+static void test_llc_prim_ms(void) +{ + struct osmo_gprs_llc_prim *llc_prim; + uint32_t tlli = 0xf43cec71; + int rc; + + printf("==== %s() [start] ====\n", __func__); + + rc = osmo_gprs_llc_init(OSMO_GPRS_LLC_LOCATION_MS, NULL); + OSMO_ASSERT(rc == 0); + + osmo_gprs_llc_prim_set_up_cb(test_llc_prim_up_cb, NULL); + osmo_gprs_llc_prim_set_down_cb(test_llc_prim_down_cb, NULL); + + /* Tx GMM Attach Request */ + llc_prim = osmo_gprs_llc_prim_alloc_ll_unitdata_req(tlli, OSMO_GPRS_LLC_SAPI_GMM, (uint8_t *)pdu_gmmm_attach_req, sizeof(pdu_gmmm_attach_req)); + OSMO_ASSERT(llc_prim); + rc = osmo_gprs_llc_prim_upper_down(llc_prim); + OSMO_ASSERT(rc == 0); + + /* Rx LLC-GMM-Attach-Req at MS from SGSN (should be a response message + * but we don't care about upper layers here): */ + llc_prim = osmo_gprs_llc_prim_alloc_grr_unitdata_ind(tlli, pdu_llc_gmm_att_req, sizeof(pdu_llc_gmm_att_req)); + OSMO_ASSERT(llc_prim); + rc = osmo_gprs_llc_prim_lower_up(llc_prim); + OSMO_ASSERT(rc == 0); + + printf("==== %s() [end] ====\n", __func__); +} + static void test_llc_prim_sgsn(void) { struct osmo_gprs_llc_prim *llc_prim; diff --git a/tests/llc/llc_prim_test.err b/tests/llc/llc_prim_test.err index 5bc0481..2c38469 100644 --- a/tests/llc/llc_prim_test.err +++ b/tests/llc/llc_prim_test.err @@ -1,3 +1,8 @@ +DLGLOBAL INFO Rx from upper layers: LL-UNITDATA.request +DLGLOBAL NOTICE Rx LL-UNITDATA.request: unknown TLLI 0xf43cec71, creating LLME on the fly +DLGLOBAL INFO Rx from lower layers: GRR-UNITDATA.indication +DLGLOBAL DEBUG Rx GRR-UNITDATA.indication: SAPI=1 (GMM), UI func=UI C/R=0 PM=0 E=0 IP=0 N(U)=0 FCS=f218e2 +DLGLOBAL DEBUG LLE(ffffffff/f43cec71,GMM){UNASSIGNED} Rx SAPI=1 (GMM), UI func=UI C/R=0 PM=0 E=0 IP=0 N(U)=0 FCS=f218e2 DLGLOBAL INFO Rx from lower layers: BSSGP-UL-UNITDATA.indication DLGLOBAL DEBUG Rx BSSGP-UL-UNITDATA.indication: SAPI=1 (GMM), UI func=UI C/R=0 PM=0 E=0 IP=0 N(U)=0 FCS=f218e2 DLGLOBAL NOTICE LLME(ffffffff/e1c5d364){UNASSIGNED} LLC RX: unknown TLLI 0xe1c5d364, creating LLME on the fly diff --git a/tests/llc/llc_prim_test.ok b/tests/llc/llc_prim_test.ok index 3193fed..4534568 100644 --- a/tests/llc/llc_prim_test.ok +++ b/tests/llc/llc_prim_test.ok @@ -1,4 +1,6 @@ ==== test_llc_prim_ms() [start] ==== +test_llc_prim_down_cb(): Rx GRR-UNITDATA.request l3=[01 c0 01 08 01 02 e5 e0 01 0a 00 05 f4 f4 3c ec 71 32 f4 07 00 05 00 17 19 33 43 2b 37 15 9e f9 88 79 cb a2 8c 66 21 e7 26 88 b1 98 87 9c 00 17 05 22 96 cc ] +test_llc_prim_up_cb(): Rx LL-UNITDATA.indication TLLI=0xf43cec71 SAPI=GMM l3=[08 01 01 d5 71 00 00 08 29 26 24 00 00 00 00 71 62 f2 24 6c 84 44 04 11 e5 10 00 ] ==== test_llc_prim_ms() [end] ==== ==== test_llc_prim_sgsn() [start] ==== test_llc_prim_up_cb(): Rx LL-UNITDATA.indication TLLI=0xe1c5d364 SAPI=GMM l3=[08 01 01 d5 71 00 00 08 29 26 24 00 00 00 00 71 62 f2 24 6c 84 44 04 11 e5 10 00 ]