aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-05-30 22:00:53 +0200
committerHarald Welte <laforge@gnumonks.org>2010-05-30 22:00:53 +0200
commita8aa4df813be0819c1c3e02fc3b974388a4b170e (patch)
tree3b102838e39dc81962c26cc624fe6f9510555e6f /openbsc/src
parentbd33f3d0ef006f03188664159fbcd476068fe656 (diff)
[GPRS] BSSGP: Acknowledge all SUSPEND and RESUME requests
This is of course not the correct way of dealing with it, but for now it should make the Ericsson Mobile Plafrom based phones happy (they insist to do a suspend/resume cycle before pdp ctx act)
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/gprs/gprs_bssgp.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/openbsc/src/gprs/gprs_bssgp.c b/openbsc/src/gprs/gprs_bssgp.c
index fa994514..ea1f9f88 100644
--- a/openbsc/src/gprs/gprs_bssgp.c
+++ b/openbsc/src/gprs/gprs_bssgp.c
@@ -129,6 +129,96 @@ static int bssgp_tx_fc_bvc_ack(uint16_t nsei, uint8_t tag, uint16_t ns_bvci)
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
+/* 10.3.7 SUSPEND-ACK PDU */
+int bssgp_tx_suspend_ack(uint16_t nsei, uint32_t tlli,
+ const struct gprs_ra_id *ra_id, uint8_t suspend_ref)
+{
+ struct msgb *msg = bssgp_msgb_alloc();
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
+ uint32_t _tlli;
+ uint8_t ra[6];
+
+ msgb_nsei(msg) = nsei;
+ msgb_bvci(msg) = 0; /* Signalling */
+ bgph->pdu_type = BSSGP_PDUT_SUSPEND_ACK;
+
+ _tlli = htonl(tlli);
+ msgb_tvlv_put(msg, BSSGP_IE_TLLI, 4, (uint8_t *) &_tlli);
+ gsm48_construct_ra(ra, ra_id);
+ msgb_tvlv_put(msg, BSSGP_IE_ROUTEING_AREA, 6, ra);
+ msgb_tvlv_put(msg, BSSGP_IE_SUSPEND_REF_NR, 1, &suspend_ref);
+
+ return gprs_ns_sendmsg(bssgp_nsi, msg);
+}
+
+/* 10.3.8 SUSPEND-NACK PDU */
+int bssgp_tx_suspend_nack(uint16_t nsei, uint32_t tlli,
+ uint8_t *cause)
+{
+ struct msgb *msg = bssgp_msgb_alloc();
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
+ uint32_t _tlli;
+
+ msgb_nsei(msg) = nsei;
+ msgb_bvci(msg) = 0; /* Signalling */
+ bgph->pdu_type = BSSGP_PDUT_SUSPEND_NACK;
+
+ _tlli = htonl(tlli);
+ msgb_tvlv_put(msg, BSSGP_IE_TLLI, 4, (uint8_t *) &_tlli);
+ if (cause)
+ msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, cause);
+
+ return gprs_ns_sendmsg(bssgp_nsi, msg);
+}
+
+/* 10.3.10 RESUME-ACK PDU */
+int bssgp_tx_resume_ack(uint16_t nsei, uint32_t tlli,
+ const struct gprs_ra_id *ra_id)
+{
+ struct msgb *msg = bssgp_msgb_alloc();
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
+ uint32_t _tlli;
+ uint8_t ra[6];
+
+ msgb_nsei(msg) = nsei;
+ msgb_bvci(msg) = 0; /* Signalling */
+ bgph->pdu_type = BSSGP_PDUT_RESUME_ACK;
+
+ _tlli = htonl(tlli);
+ msgb_tvlv_put(msg, BSSGP_IE_TLLI, 4, (uint8_t *) &_tlli);
+ gsm48_construct_ra(ra, ra_id);
+ msgb_tvlv_put(msg, BSSGP_IE_ROUTEING_AREA, 6, ra);
+
+ return gprs_ns_sendmsg(bssgp_nsi, msg);
+}
+
+/* 10.3.11 RESUME-NACK PDU */
+int bssgp_tx_resume_nack(uint16_t nsei, uint32_t tlli,
+ const struct gprs_ra_id *ra_id, uint8_t *cause)
+{
+ struct msgb *msg = bssgp_msgb_alloc();
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
+ uint32_t _tlli;
+ uint8_t ra[6];
+
+ msgb_nsei(msg) = nsei;
+ msgb_bvci(msg) = 0; /* Signalling */
+ bgph->pdu_type = BSSGP_PDUT_SUSPEND_NACK;
+
+ _tlli = htonl(tlli);
+ msgb_tvlv_put(msg, BSSGP_IE_TLLI, 4, (uint8_t *) &_tlli);
+ gsm48_construct_ra(ra, ra_id);
+ msgb_tvlv_put(msg, BSSGP_IE_ROUTEING_AREA, 6, ra);
+ if (cause)
+ msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, cause);
+
+ return gprs_ns_sendmsg(bssgp_nsi, msg);
+}
+
uint16_t bssgp_parse_cell_id(struct gprs_ra_id *raid, const uint8_t *buf)
{
/* 6 octets RAC */
@@ -267,6 +357,8 @@ static int bssgp_rx_suspend(struct msgb *msg, struct tlv_parsed *tp,
{
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_bssgph(msg);
+ struct gprs_ra_id raid;
+ uint32_t tlli;
DEBUGP(DBSSGP, "BSSGP SUSPEND\n");
@@ -274,8 +366,13 @@ static int bssgp_rx_suspend(struct msgb *msg, struct tlv_parsed *tp,
!TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA))
return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
+ tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI));
+ gsm48_parse_ra(&raid, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA));
+
/* FIXME: pass the SUSPEND request to GMM */
/* SEND SUSPEND_ACK or SUSPEND_NACK */
+ bssgp_tx_suspend_ack(msgb_nsei(msg), tlli, &raid, 0);
+
return 0;
}
@@ -284,6 +381,8 @@ static int bssgp_rx_resume(struct msgb *msg, struct tlv_parsed *tp,
{
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_bssgph(msg);
+ struct gprs_ra_id raid;
+ uint32_t tlli;
DEBUGP(DBSSGP, "BSSGP RESUME\n");
@@ -292,8 +391,12 @@ static int bssgp_rx_resume(struct msgb *msg, struct tlv_parsed *tp,
!TLVP_PRESENT(tp, BSSGP_IE_SUSPEND_REF_NR))
return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
+ tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI));
+ gsm48_parse_ra(&raid, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA));
+
/* FIXME: pass the RESUME request to GMM */
/* SEND RESUME_ACK or RESUME_NACK */
+ bssgp_tx_resume_ack(msgb_nsei(msg), tlli, &raid);
return 0;
}