aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-05-18 14:32:29 +0200
committerHarald Welte <laforge@gnumonks.org>2010-05-18 14:32:29 +0200
commit77289c202f1e0a748a31d473f7b64c6728377950 (patch)
treef92678140fbbf5625adb5d2ae0db2001938ca4e6
parent55e0df7c431b6c2e8114c663092ab2c2f1a3e8d8 (diff)
[GPRS] SGSN: properly delete a PDP context after receiving PDP CTX DEACT REQ
-rw-r--r--openbsc/include/openbsc/gprs_gmm.h3
-rw-r--r--openbsc/include/openbsc/gprs_sgsn.h6
-rw-r--r--openbsc/include/openbsc/sgsn.h4
-rw-r--r--openbsc/src/gprs/gprs_gmm.c46
-rw-r--r--openbsc/src/gprs/gprs_ns.c4
-rw-r--r--openbsc/src/gprs/gprs_sgsn.c32
-rw-r--r--openbsc/src/gprs/sgsn_libgtp.c33
-rw-r--r--openbsc/src/gprs/sgsn_main.c6
-rw-r--r--openbsc/src/gprs/sgsn_vty.c8
9 files changed, 95 insertions, 47 deletions
diff --git a/openbsc/include/openbsc/gprs_gmm.h b/openbsc/include/openbsc/gprs_gmm.h
index 44a28cf83..0d03dd91f 100644
--- a/openbsc/include/openbsc/gprs_gmm.h
+++ b/openbsc/include/openbsc/gprs_gmm.h
@@ -3,8 +3,9 @@
int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
uint8_t cause, uint8_t pco_len, uint8_t *pco_v);
-
int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp);
+int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp);
+
int gsm0408_gprs_rcvmsg(struct msgb *msg);
#endif /* _GPRS_GMM_H */
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 59bf5c097..b7e0a1b96 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -148,12 +148,14 @@ struct sgsn_pdp_ctx {
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
uint8_t nsapi);
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
+ uint8_t tid);
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
uint8_t nsapi);
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
-struct ggsn_ctx {
+struct sgsn_ggsn_ctx {
struct llist_head list;
uint32_t id;
unsigned int gtp_version;
@@ -166,7 +168,7 @@ struct ggsn_ctx *ggsn_ctx_find_alloc(uint32_t id);
struct apn_ctx {
struct llist_head list;
- struct ggsn_ctx *ggsn;
+ struct sgsn_ggsn_ctx *ggsn;
char *name;
char *description;
};
diff --git a/openbsc/include/openbsc/sgsn.h b/openbsc/include/openbsc/sgsn.h
index 1633b834d..a90a8643c 100644
--- a/openbsc/include/openbsc/sgsn.h
+++ b/openbsc/include/openbsc/sgsn.h
@@ -46,8 +46,10 @@ int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg);
int sgsn_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci);
-struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct ggsn_ctx *ggsn,
+struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
struct sgsn_mm_ctx *mmctx,
uint16_t nsapi,
struct tlv_parsed *tp);
+int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
+
#endif
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 474c7f238..3eddaff10 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -54,6 +54,7 @@
#include <pdp.h>
extern struct sgsn_instance *sgsn;
+extern struct ggsn_ctx *dummy_ggsn;
/* Protocol related stuff, should go into libosmocore */
@@ -530,8 +531,6 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
struct gprs_ra_id old_ra_id;
uint8_t upd_type;
- rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_RA_UPDATE]);
-
/* Update Type 10.5.5.18 */
upd_type = *cur++ & 0x0f;
@@ -572,6 +571,8 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
/* FIXME: Update the MM context with the MS radio acc capabilities */
/* FIXME: Update the MM context with the MS network capabilities */
+ rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_RA_UPDATE]);
+
DEBUGPC(DMM, " ACCEPT\n");
return gsm48_tx_gmm_ra_upd_ack(msg);
}
@@ -596,6 +597,7 @@ static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
gh->msg_type != GSM48_MT_GMM_ATTACH_REQ &&
gh->msg_type != GSM48_MT_GMM_RA_UPD_REQ) {
LOGP(DMM, LOGL_NOTICE, "Cannot handle GMM for unknown MM CTX\n");
+ /* FIXME: Send GMM_CAUSE_IMPL_DETACHED */
return -EINVAL;
}
@@ -683,8 +685,8 @@ int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp)
/* PDP address */
msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR,
pdp->lib->eua.l, pdp->lib->eua.v);
- /* Optional: Protocol configuration options */
- if (pdp->lib->pco_neg.l && pdp->lib->pco_neg.v)
+ /* Optional: Protocol configuration options (FIXME: why 'req') */
+ if (pdp->lib->pco_req.l && pdp->lib->pco_req.v)
msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT,
pdp->lib->pco_neg.l, pdp->lib->pco_neg.v);
/* Optional: Packet Flow Identifier */
@@ -701,7 +703,7 @@ int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
struct gsm48_hdr *gh;
uint8_t transaction_id = tid ^ 0x8; /* flip */
- DEBUGP(DMM, "<- ACTIVATE PDP CONTEXT REJ\n");
+ DEBUGP(DMM, "<- ACTIVATE PDP CONTEXT REJ(cause=%u)\n", cause);
mmctx2msgid(msg, mm);
@@ -717,23 +719,22 @@ int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
}
/* Section 9.5.9: Deactivate PDP Context Accept */
-static int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_mm_ctx *mmctx,
- struct msgb *old_msg)
+int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp)
{
- struct gsm48_hdr *old_gh = (struct gsm48_hdr *) msgb_gmmh(old_msg);
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
- uint8_t transaction_id = ((old_gh->proto_discr >> 4) ^ 0x8); /* flip */
+ uint8_t transaction_id = pdp->ti ^ 0x8; /* flip */
+ int rc;
DEBUGP(DMM, "<- DEACTIVATE PDP CONTEXT ACK\n");
- gmm_copy_id(msg, old_msg);
+ mmctx2msgid(msg, pdp->mm);
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK;
- return gsm48_gmm_sendmsg(msg, 0, mmctx);
+ return gsm48_gmm_sendmsg(msg, 0, pdp->mm);
}
/* Section 9.5.1: Activate PDP Context Request */
@@ -791,6 +792,8 @@ static int gsm48_rx_gsm_act_pdp_req(struct sgsn_mm_ctx *mmctx,
break;
}
+ DEBUGPC(DMM, "\n");
+
/* put the non-TLV elements in the TLV parser structure to
* pass them on to the SGSN / GTP code */
tp.lv[OSMO_IE_GSM_REQ_QOS].len = req_qos_len;
@@ -819,11 +822,7 @@ static int gsm48_rx_gsm_act_pdp_req(struct sgsn_mm_ctx *mmctx,
#if 1
{
- struct ggsn_ctx ggsn;
- ggsn.gtp_version = 1;
- inet_aton("192.168.100.239", &ggsn.remote_addr);
- ggsn.gsn = sgsn->gsn;
- pdp = sgsn_create_pdp_ctx(&ggsn, mmctx, act_req->req_nsapi, &tp);
+ pdp = sgsn_create_pdp_ctx(dummy_ggsn, mmctx, act_req->req_nsapi, &tp);
if (!pdp)
return -1;
pdp->sapi = act_req->req_llc_sapi;
@@ -836,14 +835,24 @@ static int gsm48_rx_gsm_act_pdp_req(struct sgsn_mm_ctx *mmctx,
}
/* Section 9.5.8: Deactivate PDP Context Request */
-static int gsm48_rx_gsm_deact_pdp_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
+static int gsm48_rx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, struct msgb *msg)
{
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ uint8_t transaction_id = (gh->proto_discr >> 4);
+ struct sgsn_pdp_ctx *pdp;
DEBUGP(DMM, "-> DEACTIVATE PDP CONTEXT REQ (cause: %s)\n",
get_value_string(gsm_cause_names, gh->data[0]));
- return gsm48_tx_gsm_deact_pdp_acc(ctx, msg);
+ pdp = sgsn_pdp_ctx_by_tid(mm, transaction_id);
+ if (!pdp) {
+ LOGP(DMM, LOGL_NOTICE, "Deactivate PDP Context Request for "
+ "non-existing PDP Context (IMSI=%s, TI=%u)\n",
+ mm->imsi, transaction_id);
+ return -EINVAL;
+ }
+
+ return sgsn_delete_pdp_ctx(pdp);
}
static int gsm48_rx_gsm_status(struct sgsn_mm_ctx *ctx, struct msgb *msg)
@@ -873,6 +882,7 @@ static int gsm0408_rcv_gsm(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
break;
case GSM48_MT_GSM_DEACT_PDP_REQ:
rc = gsm48_rx_gsm_deact_pdp_req(mmctx, msg);
+ break;
case GSM48_MT_GSM_STATUS:
rc = gsm48_rx_gsm_status(mmctx, msg);
break;
diff --git a/openbsc/src/gprs/gprs_ns.c b/openbsc/src/gprs/gprs_ns.c
index 7b1b13871..6d028aba1 100644
--- a/openbsc/src/gprs/gprs_ns.c
+++ b/openbsc/src/gprs/gprs_ns.c
@@ -667,9 +667,13 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
nsvc->nsvci = nsvc->nsei = 0xfffe;
nsvc->ip.bts_addr = *saddr;
nsvc->state = NSE_S_ALIVE;
+#if 0
+ return gprs_ns_tx_reset(nsvc, NS_CAUSE_PDU_INCOMP_PSTATE);
+#else
return gprs_ns_tx_status(nsvc,
NS_CAUSE_PDU_INCOMP_PSTATE, 0,
msg);
+#endif
}
rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data,
msgb_l2len(msg), 0, 0);
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index 38056f0e2..2671796ab 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -123,6 +123,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli,
return ctx;
}
+
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
uint8_t nsapi)
{
@@ -135,6 +136,19 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
return NULL;
}
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
+ uint8_t tid)
+{
+ struct sgsn_pdp_ctx *pdp;
+
+ llist_for_each_entry(pdp, &mm->pdp_list, list) {
+ if (pdp->ti == tid)
+ return pdp;
+ }
+ return NULL;
+}
+
+
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
uint8_t nsapi)
{
@@ -165,11 +179,11 @@ void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp)
/* GGSN contexts */
-struct ggsn_ctx *ggsn_ctx_alloc(uint32_t id)
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id)
{
- struct ggsn_ctx *ggc;
+ struct sgsn_ggsn_ctx *ggc;
- ggc = talloc_zero(tall_bsc_ctx, struct ggsn_ctx);
+ ggc = talloc_zero(tall_bsc_ctx, struct sgsn_ggsn_ctx);
if (!ggc)
return NULL;
@@ -179,9 +193,9 @@ struct ggsn_ctx *ggsn_ctx_alloc(uint32_t id)
return ggc;
}
-struct ggsn_ctx *ggsn_ctx_by_id(uint32_t id)
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id)
{
- struct ggsn_ctx *ggc;
+ struct sgsn_ggsn_ctx *ggc;
llist_for_each_entry(ggc, &sgsn_ggsn_ctxts, list) {
if (id == ggc->id)
@@ -190,13 +204,13 @@ struct ggsn_ctx *ggsn_ctx_by_id(uint32_t id)
return NULL;
}
-struct ggsn_ctx *ggsn_ctx_find_alloc(uint32_t id)
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id)
{
- struct ggsn_ctx *ggc;
+ struct sgsn_ggsn_ctx *ggc;
- ggc = ggsn_ctx_by_id(id);
+ ggc = sgsn_ggsn_ctx_by_id(id);
if (!ggc)
- ggc = ggsn_ctx_alloc(id);
+ ggc = sgsn_ggsn_ctx_alloc(id);
return ggc;
}
diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c
index a034e7ae2..64786de8f 100644
--- a/openbsc/src/gprs/sgsn_libgtp.c
+++ b/openbsc/src/gprs/sgsn_libgtp.c
@@ -89,7 +89,7 @@ const struct value_string gtp_cause_strs[] = {
/* generate a PDP context based on the IE's from the 04.08 message,
* and send the GTP create pdp context request to the GGSN */
-struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct ggsn_ctx *ggsn,
+struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
struct sgsn_mm_ctx *mmctx,
uint16_t nsapi,
struct tlv_parsed *tp)
@@ -99,6 +99,7 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct ggsn_ctx *ggsn,
uint64_t imsi_ui64;
int rc;
+ LOGP(DGPRS, LOGL_ERROR, "Create PDP Context\n");
pctx = sgsn_pdp_ctx_alloc(mmctx, nsapi);
if (!pctx) {
LOGP(DGPRS, LOGL_ERROR, "Couldn't allocate PDP Ctx\n");
@@ -178,6 +179,13 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct ggsn_ctx *ggsn,
return pctx;
}
+int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx)
+{
+ LOGP(DGPRS, LOGL_ERROR, "Delete PDP Context\n");
+
+ /* FIXME: decide if we need teardown or not ! */
+ return gtp_delete_context_req(pctx->ggsn->gsn, pctx->lib, pctx, 1);
+}
struct cause_map {
uint8_t cause_in;
@@ -261,20 +269,21 @@ reject:
return EOF;
}
-/* If we receive a 04.08 DEACT PDP CTX REQ or GPRS DETACH, we need to
- * look-up the PDP context and request its deletion from the SGSN */
-int sgsn_delete_pdp_ctx(struct ggsn_ctx *ggsn, struct sgsn_mm_ctx *mmctx,
- struct tlv_parsed *tp)
-{
- //return gtp_delete_context_req(gsn, pdp, cbp, teardown);
-}
-
/* Confirmation of a PDP Context Delete */
-static int delete_pdp_conf(struct pdp_t *pdp, int cause)
+static int delete_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
{
+ struct sgsn_pdp_ctx *pctx = cbp;
+ int rc;
+
DEBUGP(DGPRS, "Received DELETE PDP CTX CONF, cause=%d(%s)\n",
cause, get_value_string(gtp_cause_strs, cause));
- return 0;
+
+ /* Confirm deactivation of PDP context to MS */
+ rc = gsm48_tx_gsm_deact_pdp_acc(pctx);
+
+ sgsn_pdp_ctx_free(pctx);
+
+ return rc;
}
/* Confirmation of an GTP ECHO request */
@@ -305,7 +314,7 @@ static int cb_conf(int type, int cause, struct pdp_t *pdp, void *cbp)
case GTP_CREATE_PDP_REQ:
return create_pdp_conf(pdp, cbp, cause);
case GTP_DELETE_PDP_REQ:
- return delete_pdp_conf(pdp, cause);
+ return delete_pdp_conf(pdp, cbp, cause);
default:
break;
}
diff --git a/openbsc/src/gprs/sgsn_main.c b/openbsc/src/gprs/sgsn_main.c
index 2a119e3a8..e72d398a1 100644
--- a/openbsc/src/gprs/sgsn_main.c
+++ b/openbsc/src/gprs/sgsn_main.c
@@ -123,6 +123,8 @@ static void signal_handler(int signal)
/* NSI that BSSGP uses when transmitting on NS */
extern struct gprs_ns_inst *bssgp_nsi;
extern void *tall_msgb_ctx;
+static struct sgsn_ggsn_ctx _ggsn;
+struct sgsn_ggsn_ctx *dummy_ggsn = &_ggsn;
int main(int argc, char **argv)
{
@@ -174,6 +176,10 @@ int main(int argc, char **argv)
rc = sgsn_gtp_init(&sgsn_inst);
nsip_listen(sgsn_nsi, sgsn_inst.cfg.nsip_listen_port);
+ _ggsn.gtp_version = 1;
+ inet_aton("192.168.100.239", &_ggsn.remote_addr);
+ _ggsn.gsn = sgsn_inst.gsn;
+
while (1) {
rc = bsc_select_main(0);
if (rc < 0)
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index 212f0e6e2..4fe3e9711 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -49,7 +49,7 @@ static struct cmd_node sgsn_node = {
static int config_write_sgsn(struct vty *vty)
{
struct in_addr ia;
- struct ggsn_ctx *gctx;
+ struct sgsn_ggsn_ctx *gctx;
vty_out(vty, "sgsn%s", VTY_NEWLINE);
@@ -111,7 +111,7 @@ DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
"")
{
uint32_t id = atoi(argv[0]);
- struct ggsn_ctx *ggc = ggsn_ctx_find_alloc(id);
+ struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
inet_aton(argv[1], &ggc->remote_addr);
@@ -124,7 +124,7 @@ DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
"")
{
uint32_t id = atoi(argv[0]);
- struct ggsn_ctx *ggc = ggsn_ctx_find_alloc(id);
+ struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
uint16_t port = atoi(argv[1]);
}
@@ -135,7 +135,7 @@ DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
"")
{
uint32_t id = atoi(argv[0]);
- struct ggsn_ctx *ggc = ggsn_ctx_find_alloc(id);
+ struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
uint16_t port = atoi(argv[1]);
if (atoi(argv[1]))