On 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 <[email protected]>
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) {

Reply via email to