diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-05-13 19:22:55 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-05-13 21:29:11 +0200 |
commit | 1ae09c7bd6c47d768e641d598f966e6b8c77c2bc (patch) | |
tree | dff9104078156557157efb0cfae87be299f455e9 | |
parent | e15ad48a828a46400dd62b5dafe247059f03b4a7 (diff) |
[GPRS] LLC: Improve implementation compliance to spec
Don't allocate a LLC Entity just because BSSGP passes any random
SAPI/TLLI up to us. We can only do this for XID and UI frames
of the GMM SAPI.
Furthermore, add more comments and debug messages.
-rw-r--r-- | openbsc/include/openbsc/gprs_llc.h | 36 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_llc.c | 55 |
2 files changed, 78 insertions, 13 deletions
diff --git a/openbsc/include/openbsc/gprs_llc.h b/openbsc/include/openbsc/gprs_llc.h index 5a6682d80..608fb0578 100644 --- a/openbsc/include/openbsc/gprs_llc.h +++ b/openbsc/include/openbsc/gprs_llc.h @@ -26,7 +26,43 @@ enum gprs_llc_u_cmd { GPRS_LLC_U_NULL_CMD = 0x00, }; +/* TS 04.64 Section 7.1.2 Table 7: LLC layer primitives (GMM/SNDCP/SMS/TOM) */ +/* TS 04.65 Section 5.1.2 Table 2: Service primitives used by SNDCP */ +enum gprs_llc_primitive { + /* GMM <-> LLME */ + LLGMM_ASSIGN_REQ, /* GMM tells us new TLLI: TLLI old, TLLI new, Kc, CiphAlg */ + LLGMM_RESET_REQ, /* GMM tells us to perform XID negotiation: TLLI */ + LLGMM_RESET_CNF, /* LLC informs GMM that XID has completed: TLLI */ + LLGMM_SUSPEND_REQ, /* GMM tells us MS has suspended: TLLI, Page */ + LLGMM_RESUME_REQ, /* GMM tells us MS has resumed: TLLI */ + LLGMM_PAGE_IND, /* LLC asks GMM to page MS: TLLI */ + LLGMM_IOV_REQ, /* GMM tells us to perform XID: TLLI */ + LLGMM_STATUS_IND, /* LLC informs GMM about error: TLLI, Cause */ + /* LLE <-> (GMM/SNDCP/SMS/TOM) */ + LL_RESET_IND, /* TLLI */ + LL_ESTABLISH_REQ, /* TLLI, XID Req */ + LL_ESTABLISH_IND, /* TLLI, XID Req, N201-I, N201-U */ + LL_ESTABLISH_RESP, /* TLLI, XID Negotiated */ + LL_ESTABLISH_CONF, /* TLLI, XID Neg, N201-i, N201-U */ + LL_RELEASE_REQ, /* TLLI, Local */ + LL_RELEASE_IND, /* TLLI, Cause */ + LL_RELEASE_CONF, /* TLLI */ + LL_XID_REQ, /* TLLI, XID Requested */ + LL_XID_IND, /* TLLI, XID Req, N201-I, N201-U */ + LL_XID_RESP, /* TLLI, XID Negotiated */ + LL_XID_CONF, /* TLLI, XID Neg, N201-I, N201-U */ + LL_DATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */ + LL_DATA_IND, /* TLLI, SN-PDU */ + LL_DATA_CONF, /* TLLI, Ref */ + LL_UNITDATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */ + LL_UNITDATA_IND, /* TLLI, SN-PDU */ + LL_STATUS_IND, /* TLLI, Cause */ +}; + +/* BSSGP-UL-UNITDATA.ind */ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv); + +/* LL-UNITDATA.req */ int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command); #endif diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c index 9c75a3d4e..c3df01352 100644 --- a/openbsc/src/gprs/gprs_llc.c +++ b/openbsc/src/gprs/gprs_llc.c @@ -111,6 +111,7 @@ enum gprs_llc_cmd { GPRS_LLC_SABM, GPRS_LLC_FRMR, GPRS_LLC_XID, + GPRS_LLC_UI, }; struct gprs_llc_hdr_parsed { @@ -156,13 +157,13 @@ static void t200_expired(void *data) switch (lle->state) { case GPRS_LLS_LOCAL_EST: - /* retransmit SABM */ - /* re-start T200 */ + /* FIXME: retransmit SABM */ + /* FIXME: re-start T200 */ lle->retrans_ctr++; break; case GPRS_LLS_LOCAL_REL: - /* retransmit DISC */ - /* re-start T200 */ + /* FIXME: retransmit DISC */ + /* FIXME: re-start T200 */ lle->retrans_ctr++; break; } @@ -174,8 +175,8 @@ static void t201_expired(void *data) struct gprs_llc_lle *lle = data; if (lle->retrans_ctr < lle->n200) { - /* transmit apropriate supervisory frame (8.6.4.1) */ - /* set timer T201 */ + /* FIXME: transmit apropriate supervisory frame (8.6.4.1) */ + /* FIXME: set timer T201 */ lle->retrans_ctr++; } } @@ -213,6 +214,7 @@ int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi, int command, /* Identifiers passed down: (BVCI, NSEI) */ + /* Send BSSGP-DL-UNITDATA.req */ return gprs_bssgp_tx_dl_ud(msg); } @@ -272,6 +274,7 @@ int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command) /* Identifiers passed down: (BVCI, NSEI) */ + /* Send BSSGP-DL-UNITDATA.req */ return gprs_bssgp_tx_dl_ud(msg); } @@ -437,6 +440,7 @@ static int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp, } } else if ((ctrl[0] & 0xe0) == 0xc0) { /* UI (Unconfirmed Inforamtion) format */ + ghp->cmd = GPRS_LLC_UI; ghp->data = ctrl + 2; ghp->data_len = (llc_hdr + len - 3) - ghp->data; @@ -491,6 +495,12 @@ static int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp, ghp->fcs_calc = gprs_llc_fcs(llc_hdr, crc_length); /* FIXME: parse sack frame */ + if (ghp->cmd == GPRS_LLC_SACK) { + DEBUGP(DGPRS, "Unsupported SACK frame\n"); + return -EIO; + } + + return 0; } /* receive an incoming LLC PDU (BSSGP-UL-UNITDATA-IND, 7.2.4.2) */ @@ -505,37 +515,56 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv) /* Identifiers from DOWN: NSEI, BVCI, TLLI */ rc = gprs_llc_hdr_parse(&llhp, lh, TLVP_LEN(tv, BSSGP_IE_LLC_PDU)); - /* FIXME */ - gprs_llc_hdr_dump(&llhp); + if (rc < 0) { + DEBUGP(DGPRS, "Error during LLC header parsing\n"); + return rc; + } + + if (llhp.fcs != llhp.fcs_calc) { + DEBUGP(DGPRS, "Dropping frame with invalid FCS\n"); + return -EIO; + } /* find the LLC Entity for this TLLI+SAPI tuple */ lle = lle_by_tlli_sapi(msgb_tlli(msg), llhp.sapi); - /* allocate a new LLE if needed */ - if (!lle) + + /* 7.2.1.1 LLC belonging to unassigned TLLI+SAPI shall be discarded, + * except UID and XID frames with SAPI=1 */ + if (!lle && llhp.sapi == GPRS_SAPI_GMM && + (llhp.cmd == GPRS_LLC_XID || llhp.cmd == GPRS_LLC_UI)) { + /* FIXME: don't use the TLLI but the 0xFFFF unassigned? */ lle = lle_alloc(msgb_tlli(msg), llhp.sapi); + } else { + DEBUGP(DGPRS, "unknown TLLI/SAPI: Silently dropping\n"); + return 0; + } /* Update LLE's (BVCI, NSEI) tuple */ lle->bvci = msgb_bvci(msg); lle->nsei = msgb_nsei(msg); + /* Receive and Process the actual LLC frame */ rc = gprs_llc_hdr_rx(&llhp, lle); - /* FIXME */ + if (rc < 0) + return rc; + /* llhp.data is only set when we need to send LL_[UNIT]DATA_IND up */ if (llhp.data) { msgb_gmmh(msg) = llhp.data; switch (llhp.sapi) { case GPRS_SAPI_GMM: + /* send LL_UNITDATA_IND to GMM */ rc = gsm0408_gprs_rcvmsg(msg); break; case GPRS_SAPI_TOM2: case GPRS_SAPI_TOM8: - /* FIXME */ + /* FIXME: send LL_DATA_IND/LL_UNITDATA_IND to TOM */ case GPRS_SAPI_SNDCP3: case GPRS_SAPI_SNDCP5: case GPRS_SAPI_SNDCP9: case GPRS_SAPI_SNDCP11: - /* FIXME */ + /* FIXME: send LL_DATA_IND/LL_UNITDATA_IND to SNDCP */ case GPRS_SAPI_SMS: /* FIXME */ default: |