aboutsummaryrefslogtreecommitdiffstats
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
commit02ea86fa718714684d0dc24b512747e0c4269a67 (patch)
tree1403f02dd333d1d7dd0846fc4bd592eb74d5a775
parent6bdee6ada3f75e6e64ae311fae2716376ddd0016 (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)
-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 fa994514f..ea1f9f88c 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;
}