aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-05-02 11:19:37 +0200
committerHarald Welte <laforge@gnumonks.org>2010-05-04 07:20:43 +0200
commite6afd6077999406b91be9163e454f993929c2317 (patch)
treeae0cb21504d08698ac9a94f2a96682a5f2b63dea
parentfd3fa1d4e0aaf06e523d3f36ce5d983b77569fbc (diff)
[gprs] SGSN: Expect all Identifiers to be stored at highest level
We now expect the highest level (actual SGSN GMM code) to know all identifiers for every element in the protocol stack, i.e. TLLI, SAPI, BVCI and NSEI. The layer-inetrnal state is looked up based on those identifiers. The reason for this is to ensure only the highest level state needs to be persistent, while everything else can be regenerated dynamically (e.g. in a SGSN restart)
-rw-r--r--openbsc/include/openbsc/gprs_bssgp.h2
-rw-r--r--openbsc/include/openbsc/gsm_data.h2
-rw-r--r--openbsc/src/gprs_bssgp.c63
-rw-r--r--openbsc/src/gprs_llc.c17
-rw-r--r--openbsc/src/gprs_ns.c1
-rw-r--r--openbsc/src/sgsn_main.c2
6 files changed, 64 insertions, 23 deletions
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 <osmocore/tlv.h>
-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/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index f011041e5..3dd7a18c2 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -84,9 +84,11 @@ struct openbsc_msgb_cb {
unsigned char *bssgph;
unsigned char *llch;
+ /* Identifiers of a BTS, equal to 'struct bssgp_bts_ctx' */
u_int16_t nsei;
u_int16_t bvci;
+ /* Identifier of a MS (inside BTS), equal to 'struct sgsn_mm_ctx' */
u_int32_t tlli;
} __attribute__((packed));
#define OBSC_MSGB_CB(__msgb) ((struct openbsc_msgb_cb *)&((__msgb)->cb[0]))
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_llc.c b/openbsc/src/gprs_llc.c
index 883eedb05..ba031a2ec 100644
--- a/openbsc/src/gprs_llc.c
+++ b/openbsc/src/gprs_llc.c
@@ -61,6 +61,10 @@ struct gprs_llc_lle {
unsigned int n200;
unsigned int retrans_ctr;
+
+ /* over which BSSGP BTS ctx do we need to transmit */
+ uint16_t bvci;
+ uint16_t nsei;
};
static LLIST_HEAD(gprs_llc_lles);
@@ -190,11 +194,22 @@ static void t201_expired(void *data)
/* Transmit a UI frame over the given SAPI */
int gprs_llc_tx_ui(struct msgb *msg, u_int8_t sapi, int command)
{
+ struct gprs_llc_lle *lle;
u_int8_t *fcs, *llch;
u_int8_t addr, ctrl[2];
u_int32_t fcs_calc;
u_int16_t nu = 0;
+ /* Identifiers from UP: (TLLI, SAPI) + (BVCI, NSEI) */
+
+ /* look-up or create the LL Entity for this (TLLI, SAPI) tuple */
+ lle = lle_by_tlli_sapi(msgb_tlli(msg), sapi);
+ if (!lle)
+ lle = lle_alloc(msgb_tlli(msg), sapi);
+ /* Update LLE's (BVCI, NSEI) tuple */
+ lle->bvci = msgb_bvci(msg);
+ lle->nsei = msgb_nsei(msg);
+
/* Address Field */
addr = sapi & 0xf;
if (command)
@@ -219,6 +234,8 @@ int gprs_llc_tx_ui(struct msgb *msg, u_int8_t sapi, int command)
fcs[1] = (fcs_calc >> 8) & 0xff;
fcs[2] = (fcs_calc >> 16) & 0xff;
+ /* Identifiers passed down: (BVCI, NSEI) */
+
return gprs_bssgp_tx_dl_ud(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);
diff --git a/openbsc/src/sgsn_main.c b/openbsc/src/sgsn_main.c
index 5c56ca7ff..66d8efc4b 100644
--- a/openbsc/src/sgsn_main.c
+++ b/openbsc/src/sgsn_main.c
@@ -77,7 +77,7 @@ static int sgsn_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
switch (event) {
case GPRS_NS_EVT_UNIT_DATA:
/* hand the message into the BSSGP implementation */
- rc = gprs_bssgp_rcvmsg(msg, bvci);
+ rc = gprs_bssgp_rcvmsg(msg);
break;
default:
LOGP(DGPRS, LOGL_ERROR, "SGSN: Unknown event %u from NS\n", event);