This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
Holger Hans Peter Freyther holger at freyther.deOn Tue, Jul 30, 2013 at 08:03:49AM +0800, Harald Welte wrote: > > Sure, go ahead. that's what I meant by 'be brave' :) The engineer in me.. used git gui blame on the file and I found the commit that added the foreign tlli lookup. commit f0901f0067e363c0ced6254db1b45a9771640412 Author: Harald Welte <laforge at gnumonks.org> Date: Sun Dec 26 10:39:26 2010 +0100 [SGSN] Fix processing of RA Update Request regarding TLLI In case we get a RA UPD REQ on a new cell (both served by the same SGSN), the LLC stack should not allocate a ne LLE/LLME, as the latter would reset the V(u)sent / V(u)recv to zero and make the MS discard our responses. Instead, whenever the LLC stack sees a foreign TLLI, it should always convert it to the local TLLI before doing any lookup for a LLE/LLME. I had to move some code around but what I essentialy do is. 1.) I do the lookup based on the tlli... 2.) if the tlli is foreign.. I convert it and make another lookup 3.) I create the LLME on the fly or return NULL Or shall we do this... "oh we know this subscriber already" at a higher level in GMM? E.g. notice that it is a routing area update... and then free the new llme and do a tlli assignment for the foreign tlli? diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c index c3bd9d2..b637acb 100644 --- a/openbsc/src/gprs/gprs_llc.c +++ b/openbsc/src/gprs/gprs_llc.c @@ -36,6 +36,54 @@ #include <openbsc/crc24.h> #include <openbsc/sgsn.h> +enum gprs_llc_cmd { + GPRS_LLC_NULL, + GPRS_LLC_RR, + GPRS_LLC_ACK, + GPRS_LLC_RNR, + GPRS_LLC_SACK, + GPRS_LLC_DM, + GPRS_LLC_DISC, + GPRS_LLC_UA, + GPRS_LLC_SABM, + GPRS_LLC_FRMR, + GPRS_LLC_XID, + GPRS_LLC_UI, +}; + +static const struct value_string llc_cmd_strs[] = { + { GPRS_LLC_NULL, "NULL" }, + { GPRS_LLC_RR, "RR" }, + { GPRS_LLC_ACK, "ACK" }, + { GPRS_LLC_RNR, "RNR" }, + { GPRS_LLC_SACK, "SACK" }, + { GPRS_LLC_DM, "DM" }, + { GPRS_LLC_DISC, "DISC" }, + { GPRS_LLC_UA, "UA" }, + { GPRS_LLC_SABM, "SABM" }, + { GPRS_LLC_FRMR, "FRMR" }, + { GPRS_LLC_XID, "XID" }, + { GPRS_LLC_UI, "UI" }, + { 0, NULL } +}; + +struct gprs_llc_hdr_parsed { + uint8_t sapi; + uint8_t is_cmd:1, + ack_req:1, + is_encrypted:1; + uint32_t seq_rx; + uint32_t seq_tx; + uint32_t fcs; + uint32_t fcs_calc; + uint8_t *data; + uint16_t data_len; + uint16_t crc_length; + enum gprs_llc_cmd cmd; +}; + +static struct gprs_llc_llme *llme_alloc(uint32_t tlli); + /* Entry function from upper level (LLC), asking us to transmit a BSSGP PDU * to a remote MS (identified by TLLI) at a BTS identified by its BVCI and NSEI */ static int _bssgp_tx_dl_ud(struct msgb *msg, struct sgsn_mm_ctx *mmctx) @@ -162,6 +210,43 @@ static struct gprs_llc_lle *lle_by_tlli_sapi(const uint32_t tlli, uint8_t sapi) return NULL; } +/* lookup LLC Entity for RX based on DLCI (TLLI+SAPI tuple) */ +static struct gprs_llc_lle *lle_for_rx_by_tlli_sapi(const uint32_t tlli, + uint8_t sapi, enum gprs_llc_cmd cmd) +{ + struct gprs_llc_lle *lle; + + /* We already know about this TLLI */ + lle = lle_by_tlli_sapi(tlli, sapi); + if (lle) + return lle; + + /* Maybe it is a routing area update but we already know this sapi? */ + if (gprs_tlli_type(tlli) == TLLI_FOREIGN) { + lle = lle_by_tlli_sapi(tlli_foreign2local(tlli), sapi); + if (lle) + return lle; + } + + /* 7.2.1.1 LLC belonging to unassigned TLLI+SAPI shall be discarded, + * except UID and XID frames with SAPI=1 */ + if (sapi == GPRS_SAPI_GMM && + (cmd == GPRS_LLC_XID || cmd == GPRS_LLC_UI)) { + struct gprs_llc_llme *llme; + /* FIXME: don't use the TLLI but the 0xFFFF unassigned? */ + llme = llme_alloc(tlli); + LOGP(DLLC, LOGL_DEBUG, "LLC RX: unknown TLLI 0x%08x, " + "creating LLME on the fly\n", tlli); + lle = &llme->lle[sapi]; + return lle; + } + + LOGP(DLLC, LOGL_NOTICE, + "unknown TLLI(0x%08x)/SAPI(%d): Silently dropping\n", + tlli, sapi); + return NULL; +} + static void lle_init(struct gprs_llc_llme *llme, uint8_t sapi) { struct gprs_llc_lle *lle = &llme->lle[sapi]; @@ -201,52 +286,6 @@ static void llme_free(struct gprs_llc_llme *llme) talloc_free(llme); } -enum gprs_llc_cmd { - GPRS_LLC_NULL, - GPRS_LLC_RR, - GPRS_LLC_ACK, - GPRS_LLC_RNR, - GPRS_LLC_SACK, - GPRS_LLC_DM, - GPRS_LLC_DISC, - GPRS_LLC_UA, - GPRS_LLC_SABM, - GPRS_LLC_FRMR, - GPRS_LLC_XID, - GPRS_LLC_UI, -}; - -static const struct value_string llc_cmd_strs[] = { - { GPRS_LLC_NULL, "NULL" }, - { GPRS_LLC_RR, "RR" }, - { GPRS_LLC_ACK, "ACK" }, - { GPRS_LLC_RNR, "RNR" }, - { GPRS_LLC_SACK, "SACK" }, - { GPRS_LLC_DM, "DM" }, - { GPRS_LLC_DISC, "DISC" }, - { GPRS_LLC_UA, "UA" }, - { GPRS_LLC_SABM, "SABM" }, - { GPRS_LLC_FRMR, "FRMR" }, - { GPRS_LLC_XID, "XID" }, - { GPRS_LLC_UI, "UI" }, - { 0, NULL } -}; - -struct gprs_llc_hdr_parsed { - uint8_t sapi; - uint8_t is_cmd:1, - ack_req:1, - is_encrypted:1; - uint32_t seq_rx; - uint32_t seq_tx; - uint32_t fcs; - uint32_t fcs_calc; - uint8_t *data; - uint16_t data_len; - uint16_t crc_length; - enum gprs_llc_cmd cmd; -}; - #define LLC_ALLOC_SIZE 16384 #define UI_HDR_LEN 3 #define N202 4 @@ -770,25 +809,9 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv) } /* find the LLC Entity for this TLLI+SAPI tuple */ - lle = lle_by_tlli_sapi(msgb_tlli(msg), llhp.sapi); - - /* 7.2.1.1 LLC belonging to unassigned TLLI+SAPI shall be discarded, - * except UID and XID frames with SAPI=1 */ - if (!lle) { - if (llhp.sapi == GPRS_SAPI_GMM && - (llhp.cmd == GPRS_LLC_XID || llhp.cmd == GPRS_LLC_UI)) { - struct gprs_llc_llme *llme; - /* FIXME: don't use the TLLI but the 0xFFFF unassigned? */ - llme = llme_alloc(msgb_tlli(msg)); - LOGP(DLLC, LOGL_DEBUG, "LLC RX: unknown TLLI 0x%08x, " - "creating LLME on the fly\n", msgb_tlli(msg)); - lle = &llme->lle[llhp.sapi]; - } else { - LOGP(DLLC, LOGL_NOTICE, - "unknown TLLI/SAPI: Silently dropping\n"); - return 0; - } - } + lle = lle_for_rx_by_tlli_sapi(msgb_tlli(msg), llhp.sapi, llhp.cmd); + if (!lle) + return 0; /* decrypt information field + FCS, if needed! */ if (llhp.is_encrypted) {