diff --git a/openbsc/include/openbsc/gprs_bssgp.h b/openbsc/include/openbsc/gprs_bssgp.h index 3040e6a0e..a00481e4e 100644 --- a/openbsc/include/openbsc/gprs_bssgp.h +++ b/openbsc/include/openbsc/gprs_bssgp.h @@ -137,7 +137,7 @@ enum gprs_bssgp_cause { #include -extern int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t bvci); +extern int gprs_bssgp_rcvmsg(struct msgb *msg); /* Wrapper around TLV parser to parse BSSGP IEs */ static inline int bssgp_tlv_parse(struct tlv_parsed *tp, u_int8_t *buf, int len) diff --git a/openbsc/src/gprs_bssgp.c b/openbsc/src/gprs_bssgp.c index 330d8c875..6bba1af8a 100644 --- a/openbsc/src/gprs_bssgp.c +++ b/openbsc/src/gprs_bssgp.c @@ -255,7 +255,7 @@ static int bssgp_rx_bvc_reset(struct msgb *msg, struct tlv_parsed *tp, } /* Uplink unit-data */ -static int bssgp_rx_ul_ud(struct msgb *msg, u_int16_t bvci) +static int bssgp_rx_ul_ud(struct msgb *msg) { struct bssgp_ud_hdr *budh = (struct bssgp_ud_hdr *) msgb_bssgph(msg); int data_len = msgb_l3len(msg) - sizeof(*budh); @@ -273,12 +273,14 @@ static int bssgp_rx_ul_ud(struct msgb *msg, u_int16_t bvci) !TLVP_PRESENT(&tp, BSSGP_IE_LLC_PDU)) return -EIO; + /* FIXME: lookup bssgp_bts_ctx based on BVCI + NSEI */ + msgb_llch(msg) = TLVP_VAL(&tp, BSSGP_IE_LLC_PDU); return gprs_llc_rcvmsg(msg, &tp); } -static int bssgp_rx_suspend(struct msgb *msg, u_int16_t bvci) +static int bssgp_rx_suspend(struct msgb *msg) { struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); @@ -296,11 +298,11 @@ static int bssgp_rx_suspend(struct msgb *msg, u_int16_t bvci) !TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA)) return -EIO; + /* FIXME: pass the SUSPEND request to GMM */ /* SEND SUSPEND_ACK or SUSPEND_NACK */ - /* FIXME */ } -static int bssgp_rx_resume(struct msgb *msg, u_int16_t bvci) +static int bssgp_rx_resume(struct msgb *msg) { struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); @@ -319,12 +321,11 @@ static int bssgp_rx_resume(struct msgb *msg, u_int16_t bvci) !TLVP_PRESENT(&tp, BSSGP_IE_SUSPEND_REF_NR)) return -EIO; + /* FIXME: pass the RESUME request to GMM */ /* SEND RESUME_ACK or RESUME_NACK */ - /* FIXME */ } -static int bssgp_rx_fc_bvc(struct msgb *msg, struct tlv_parsed *tp, - u_int16_t ns_bvci) +static int bssgp_rx_fc_bvc(struct msgb *msg, struct tlv_parsed *tp) { DEBUGP(DGPRS, "BSSGP FC BVC\n"); @@ -336,22 +337,27 @@ static int bssgp_rx_fc_bvc(struct msgb *msg, struct tlv_parsed *tp, !TLVP_PRESENT(tp, BSSGP_IE_R_DEFAULT_MS)) return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); + /* FIXME: actually implement flow control */ + /* Send FLOW_CONTROL_BVC_ACK */ return bssgp_tx_fc_bvc_ack(msgb_nsei(msg), *TLVP_VAL(tp, BSSGP_IE_TAG), - ns_bvci); + msgb_bvci(msg)); } /* We expect msgb_bssgph() to point to the BSSGP header */ -int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t ns_bvci) +int gprs_bssgp_rcvmsg(struct msgb *msg) { struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); struct tlv_parsed tp; - u_int8_t pdu_type = bgph->pdu_type; + uint8_t pdu_type = bgph->pdu_type; int data_len = msgb_l3len(msg) - sizeof(*bgph); - u_int16_t bvci; + uint16_t bvci; /* PTP BVCI */ + uint16_t ns_bvci = msgb_bvci(msg); int rc = 0; + /* Identifiers from DOWN: NSEI, BVCI (both in msg->cb) */ + /* UNITDATA BSSGP headers have TLLI in front */ if (pdu_type != BSSGP_PDUT_UL_UNITDATA && pdu_type != BSSGP_PDUT_DL_UNITDATA) @@ -360,7 +366,7 @@ int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t ns_bvci) switch (pdu_type) { case BSSGP_PDUT_UL_UNITDATA: /* some LLC data from the MS */ - rc = bssgp_rx_ul_ud(msg, ns_bvci); + rc = bssgp_rx_ul_ud(msg); break; case BSSGP_PDUT_RA_CAPABILITY: /* BSS requests RA capability or IMSI */ @@ -370,32 +376,36 @@ int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t ns_bvci) case BSSGP_PDUT_RADIO_STATUS: DEBUGP(DGPRS, "BSSGP RADIO STATUS\n"); /* BSS informs us of some exception */ + /* FIXME: notify GMM */ break; case BSSGP_PDUT_SUSPEND: /* MS wants to suspend */ - rc = bssgp_rx_suspend(msg, ns_bvci); + rc = bssgp_rx_suspend(msg); break; case BSSGP_PDUT_RESUME: /* MS wants to resume */ - rc = bssgp_rx_resume(msg, ns_bvci); + rc = bssgp_rx_resume(msg); break; case BSSGP_PDUT_FLUSH_LL: /* BSS informs MS has moved to one cell to other cell */ DEBUGP(DGPRS, "BSSGP FLUSH LL\n"); + /* FIXME: notify GMM */ /* Send FLUSH_LL_ACK */ break; case BSSGP_PDUT_LLC_DISCARD: /* BSS informs that some LLC PDU's have been discarded */ DEBUGP(DGPRS, "BSSGP LLC DISCARDED\n"); + /* FIXME: notify GMM */ break; case BSSGP_PDUT_FLOW_CONTROL_BVC: /* BSS informs us of available bandwidth in Gb interface */ - rc = bssgp_rx_fc_bvc(msg, &tp, ns_bvci); + rc = bssgp_rx_fc_bvc(msg, &tp); break; case BSSGP_PDUT_FLOW_CONTROL_MS: /* BSS informs us of available bandwidth to one MS */ DEBUGP(DGPRS, "BSSGP FC MS\n"); - /* Send FLOW_CONTROL_MS_ACK */ + /* FIXME: actually implement flow control */ + /* FIXME: Send FLOW_CONTROL_MS_ACK */ break; case BSSGP_PDUT_BVC_BLOCK: /* BSS tells us that BVC shall be blocked */ @@ -431,6 +441,7 @@ int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t ns_bvci) break; case BSSGP_PDUT_STATUS: /* Some exception has occurred */ + /* FIXME: notify GMM */ case BSSGP_PDUT_DOWNLOAD_BSS_PFC: case BSSGP_PDUT_CREATE_BSS_PFC_ACK: case BSSGP_PDUT_CREATE_BSS_PFC_NACK: @@ -469,8 +480,8 @@ err_mand_ie: } /* 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 RAC and CID */ -int gprs_bssgp_tx_dl_ud(struct msgb *msg, const struct gprs_ra_id *raid, uint16_t cid) + * to a remote MS (identified by TLLI) at a BTS identified by its BVCI and NSEI */ +int gprs_bssgp_tx_dl_ud(struct msgb *msg) { struct bssgp_bts_ctx *bctx; struct bssgp_ud_hdr *budh; @@ -479,8 +490,19 @@ int gprs_bssgp_tx_dl_ud(struct msgb *msg, const struct gprs_ra_id *raid, uint16_ u_int16_t pdu_lifetime = 1000; /* centi-seconds */ u_int8_t qos_profile_default[3] = { 0x00, 0x00, 0x21 }; u_int16_t msg_len = msg->len; + uint16_t bvci = msgb_bvci(msg); + uint16_t nsei = msgb_nsei(msg); - bctx = btsctx_by_raid_cid(raid, cid); + /* Identifiers from UP: TLLI, BVCI, NSEI (all in msgb->cb) */ + if (bvci < 2) { + LOGP(DGPRS, LOGL_ERROR, "Cannot send DL-UD to BVCI %u\n", + bvci); + return -EINVAL; + } + + bctx = btsctx_by_bvci_nsei(bvci, nsei); + if (!bctx) + bctx = btsctx_alloc(bvci, nsei); if (msg->len > TVLV_MAX_ONEBYTE) llc_pdu_tlv_hdr_len += 1; @@ -508,8 +530,7 @@ int gprs_bssgp_tx_dl_ud(struct msgb *msg, const struct gprs_ra_id *raid, uint16_ budh->tlli = htonl(msgb_tlli(msg)); budh->pdu_type = BSSGP_PDUT_DL_UNITDATA; - msgb_nsei(msg) = bctx->nsei; - msgb_bvci(msg) = bctx->bvci; + /* Identifiers down: BVCI, NSEI (in msgb->cb) */ return gprs_ns_sendmsg(bssgp_nsi, msg); } diff --git a/openbsc/src/gprs_ns.c b/openbsc/src/gprs_ns.c index 470ccb080..1558ca146 100644 --- a/openbsc/src/gprs_ns.c +++ b/openbsc/src/gprs_ns.c @@ -267,6 +267,7 @@ static int gprs_ns_rx_unitdata(struct gprs_nsvc *nsvc, struct msgb *msg) /* spare octet in data[0] */ bvci = nsh->data[1] << 8 | nsh->data[2]; msgb_bssgph(msg) = &nsh->data[3]; + msgb_bvci(msg) = bvci; /* call upper layer (BSSGP) */ return nsvc->nsi->cb(GPRS_NS_EVT_UNIT_DATA, nsvc, msg, bvci);