aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/sgsn/sgsn.h16
-rw-r--r--src/gprs/gprs_gmm.c68
-rw-r--r--src/gprs/gprs_gmm_attach.c57
-rw-r--r--src/gprs/sgsn_vty.c108
-rw-r--r--tests/sgsn/sgsn_test.c7
5 files changed, 131 insertions, 125 deletions
diff --git a/include/osmocom/sgsn/sgsn.h b/include/osmocom/sgsn/sgsn.h
index 0a6ea29e..6e4f5ca0 100644
--- a/include/osmocom/sgsn/sgsn.h
+++ b/include/osmocom/sgsn/sgsn.h
@@ -86,20 +86,8 @@ struct sgsn_config {
/* CDR configuration */
struct sgsn_cdr cdr;
- struct {
- int T3312;
- int T3322;
- int T3350;
- int T3360;
- int T3370;
- int T3313;
- int T3314;
- int T3316;
- int T3385;
- int T3386;
- int T3395;
- int T3397;
- } timers;
+ /* Timer defintions */
+ struct osmo_tdef *T_defs;
int dynamic_lookup;
diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c
index b8b01167..db8defcc 100644
--- a/src/gprs/gprs_gmm.c
+++ b/src/gprs/gprs_gmm.c
@@ -40,6 +40,7 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/tdef.h>
#include <osmocom/crypt/auth.h>
#include <osmocom/gsm/apn.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
@@ -235,12 +236,15 @@ int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type
static void mmctx_timer_cb(void *_mm);
-static void mmctx_timer_start(struct sgsn_mm_ctx *mm, unsigned int T,
- unsigned int seconds)
+static void mmctx_timer_start(struct sgsn_mm_ctx *mm, unsigned int T)
{
+ unsigned long seconds;
if (osmo_timer_pending(&mm->timer))
LOGMMCTXP(LOGL_ERROR, mm, "Starting MM timer %u while old "
"timer %u pending\n", T, mm->T);
+
+ seconds = osmo_tdef_get(sgsn->cfg.T_defs, T, OSMO_TDEF_S, -1);
+
mm->T = T;
mm->num_T_exp = 0;
@@ -259,7 +263,11 @@ static void mmctx_timer_stop(struct sgsn_mm_ctx *mm, unsigned int T)
time_t gprs_max_time_to_idle(void)
{
- return sgsn->cfg.timers.T3314 + (sgsn->cfg.timers.T3312 + 4 * 60);
+ unsigned long T3314, T3312;
+
+ T3314 = osmo_tdef_get(sgsn->cfg.T_defs, 3314, OSMO_TDEF_S, -1);
+ T3312 = osmo_tdef_get(sgsn->cfg.T_defs, 3312, OSMO_TDEF_S, -1);
+ return T3314 + (T3312 + 4 * 60);
}
/* Send a message through the underlying layer.
@@ -449,6 +457,7 @@ int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm)
struct gsm48_hdr *gh;
struct gsm48_attach_ack *aa;
uint8_t *mid;
+ unsigned long t;
#if 0
uint8_t *ptsig;
#endif
@@ -465,7 +474,8 @@ int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm)
aa = (struct gsm48_attach_ack *) msgb_put(msg, sizeof(*aa));
aa->force_stby = 0; /* not indicated */
aa->att_result = 1; /* GPRS only */
- aa->ra_upd_timer = gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3312);
+ t = osmo_tdef_get(sgsn->cfg.T_defs, 3312, OSMO_TDEF_S, -1);
+ aa->ra_upd_timer = gprs_secs_to_tmr_floor(t);
aa->radio_prio = 4; /* lowest */
gsm48_encode_ra(&aa->ra_id, &mm->ra);
@@ -482,8 +492,8 @@ int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm)
* (fixed 44s, default value, GSM 04.08, table 11.4a) to safely limit
* the inactivity time READY->STANDBY.
*/
- msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY,
- gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3314));
+ t = osmo_tdef_get(sgsn->cfg.T_defs, 3314, OSMO_TDEF_S, -1);
+ msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY, gprs_secs_to_tmr_floor(t));
#ifdef PTMSI_ALLOC
/* Optional: Allocated P-TMSI */
@@ -1019,12 +1029,12 @@ static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
/* Request IMSI and IMEI from the MS if they are unknown */
if (!strlen(ctx->imei)) {
ctx->t3370_id_type = GSM_MI_TYPE_IMEI;
- mmctx_timer_start(ctx, 3370, sgsn->cfg.timers.T3370);
+ mmctx_timer_start(ctx, 3370);
return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMEI);
}
if (!strlen(ctx->imsi)) {
ctx->t3370_id_type = GSM_MI_TYPE_IMSI;
- mmctx_timer_start(ctx, 3370, sgsn->cfg.timers.T3370);
+ mmctx_timer_start(ctx, 3370);
return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMSI);
}
@@ -1047,7 +1057,7 @@ static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
&& !sgsn_mm_ctx_is_authenticated(ctx)) {
struct gsm_auth_tuple *at = &ctx->auth_triplet;
- mmctx_timer_start(ctx, 3360, sgsn->cfg.timers.T3360);
+ mmctx_timer_start(ctx, 3360);
return gsm48_tx_gmm_auth_ciph_req(ctx, &at->vec, at->key_seq,
false);
}
@@ -1086,7 +1096,7 @@ static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
extract_subscr_hlr(ctx);
#ifdef PTMSI_ALLOC
/* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
- mmctx_timer_start(ctx, 3350, sgsn->cfg.timers.T3350);
+ mmctx_timer_start(ctx, 3350);
ctx->t3350_mode = GMM_T3350_MODE_ATT;
#else
memset(&sig_data, 0, sizeof(sig_data));
@@ -1534,6 +1544,7 @@ static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm)
struct gsm48_hdr *gh;
struct gsm48_ra_upd_ack *rua;
uint8_t *mid;
+ unsigned long t;
rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ROUTING_AREA_ACKED]);
LOGMMCTXP(LOGL_INFO, mm, "<- ROUTING AREA UPDATE ACCEPT\n");
@@ -1547,7 +1558,8 @@ static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm)
rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua));
rua->force_stby = 0; /* not indicated */
rua->upd_result = 0; /* RA updated */
- rua->ra_upd_timer = gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3312);
+ t = osmo_tdef_get(sgsn->cfg.T_defs, 3312, OSMO_TDEF_S, -1);
+ rua->ra_upd_timer = gprs_secs_to_tmr_floor(t);
gsm48_encode_ra(&rua->ra_id, &mm->ra);
@@ -1568,8 +1580,8 @@ static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm)
#endif
/* Optional: Negotiated READY timer value */
- msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY,
- gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3314));
+ t = osmo_tdef_get(sgsn->cfg.T_defs, 3314, OSMO_TDEF_S, -1);
+ msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY, gprs_secs_to_tmr_floor(t));
/* Option: MS ID, ... */
return gsm48_gmm_sendmsg(msg, 0, mm, true);
@@ -1793,7 +1805,7 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
/* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
mmctx->t3350_mode = GMM_T3350_MODE_RAU;
- mmctx_timer_start(mmctx, 3350, sgsn->cfg.timers.T3350);
+ mmctx_timer_start(mmctx, 3350);
#else
/* Make sure we are NORMAL (i.e. not SUSPENDED anymore) */
mmctx->gmm_state = GMM_REGISTERED_NORMAL;
@@ -2183,6 +2195,7 @@ static void mmctx_timer_cb(void *_mm)
struct sgsn_mm_ctx *mm = _mm;
struct gsm_auth_tuple *at;
int rc;
+ unsigned long seconds;
mm->num_T_exp++;
@@ -2210,7 +2223,8 @@ static void mmctx_timer_cb(void *_mm)
"T3350 mode wasn't set, ignoring timeout\n");
break;
}
- osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3350, 0);
+ seconds = osmo_tdef_get(sgsn->cfg.T_defs, 3350, OSMO_TDEF_S, -1);
+ osmo_timer_schedule(&mm->timer, seconds, 0);
break;
case 3360: /* waiting for AUTH AND CIPH RESP */
if (mm->num_T_exp >= 5) {
@@ -2228,10 +2242,12 @@ static void mmctx_timer_cb(void *_mm)
at = &mm->auth_triplet;
rc = gsm48_tx_gmm_auth_ciph_req(mm, &at->vec, at->key_seq, false);
- if (rc < 0)
+ if (rc < 0) {
LOGMMCTXP(LOGL_ERROR, mm, "failed sending Auth. & Ciph. Request: %s \n", strerror(-rc));
- else
- osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3360, 0);
+ } else {
+ seconds = osmo_tdef_get(sgsn->cfg.T_defs, 3360, OSMO_TDEF_S, -1);
+ osmo_timer_schedule(&mm->timer, seconds, 0);
+ }
break;
case 3370: /* waiting for IDENTITY RESPONSE */
if (mm->num_T_exp >= 5) {
@@ -2242,7 +2258,8 @@ static void mmctx_timer_cb(void *_mm)
}
/* re-tranmit IDENTITY REQUEST and re-start timer */
gsm48_tx_gmm_id_req(mm, mm->t3370_id_type);
- osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3370, 0);
+ seconds = osmo_tdef_get(sgsn->cfg.T_defs, 3370, OSMO_TDEF_S, -1);
+ osmo_timer_schedule(&mm->timer, seconds, 0);
break;
default:
LOGMMCTXP(LOGL_ERROR, mm, "timer expired in unknown mode %u\n",
@@ -2255,16 +2272,17 @@ static void mmctx_timer_cb(void *_mm)
static void pdpctx_timer_cb(void *_mm);
-static void pdpctx_timer_rearm(struct sgsn_pdp_ctx *pdp, unsigned int T, unsigned int seconds)
+static void pdpctx_timer_rearm(struct sgsn_pdp_ctx *pdp, unsigned int T)
{
+ unsigned long seconds;
if (osmo_timer_pending(&pdp->timer))
LOGPDPCTXP(LOGL_ERROR, pdp, "Scheduling PDP timer %u while old "
"timer %u pending\n", T, pdp->T);
+ seconds = osmo_tdef_get(sgsn->cfg.T_defs, T, OSMO_TDEF_S, -1);
osmo_timer_schedule(&pdp->timer, seconds, 0);
}
-static void pdpctx_timer_start(struct sgsn_pdp_ctx *pdp, unsigned int T,
- unsigned int seconds)
+static void pdpctx_timer_start(struct sgsn_pdp_ctx *pdp, unsigned int T)
{
if (osmo_timer_pending(&pdp->timer))
LOGPDPCTXP(LOGL_ERROR, pdp, "Starting PDP timer %u while old "
@@ -2273,7 +2291,7 @@ static void pdpctx_timer_start(struct sgsn_pdp_ctx *pdp, unsigned int T,
pdp->num_T_exp = 0;
osmo_timer_setup(&pdp->timer, pdpctx_timer_cb, pdp);
- pdpctx_timer_rearm(pdp, pdp->T, seconds);
+ pdpctx_timer_rearm(pdp, pdp->T);
}
static void pdpctx_timer_stop(struct sgsn_pdp_ctx *pdp, unsigned int T)
@@ -2410,7 +2428,7 @@ static int _gsm48_tx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, uint8_t tid,
}
int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause, bool teardown)
{
- pdpctx_timer_start(pdp, 3395, sgsn->cfg.timers.T3395);
+ pdpctx_timer_start(pdp, 3395);
return _gsm48_tx_gsm_deact_pdp_req(pdp->mm, pdp->ti, sm_cause, teardown);
}
@@ -2826,7 +2844,7 @@ static void pdpctx_timer_cb(void *_pdp)
break;
}
_gsm48_tx_gsm_deact_pdp_req(pdp->mm, pdp->ti, GSM_CAUSE_NET_FAIL, true);
- pdpctx_timer_rearm(pdp, 3395, sgsn->cfg.timers.T3395);
+ pdpctx_timer_rearm(pdp, 3395);
break;
default:
LOGPDPCTXP(LOGL_ERROR, pdp, "timer expired in unknown mode %u\n",
diff --git a/src/gprs/gprs_gmm_attach.c b/src/gprs/gprs_gmm_attach.c
index 2217b0ab..130f8d1c 100644
--- a/src/gprs/gprs_gmm_attach.c
+++ b/src/gprs/gprs_gmm_attach.c
@@ -1,3 +1,5 @@
+#include <osmocom/core/tdef.h>
+
#include <osmocom/sgsn/gprs_gmm_attach.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
@@ -10,6 +12,18 @@
static int require_identity_imei = 1;
static int require_auth = 1;
+static const struct osmo_tdef_state_timeout gmm_attach_fsm_timeouts[32] = {
+ [ST_IDENTIY] = { .T=3370 },
+ [ST_AUTH] = { .T=3360 },
+ [ST_ACCEPT] = { .T=3350 },
+ [ST_ASK_VLR] = { .T=3350 },
+ [ST_IU_SECURITY_CMD] = { .T=3350 },
+};
+
+#define gmm_attach_fsm_state_chg(fi, NEXT_STATE) \
+ osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, gmm_attach_fsm_timeouts, sgsn->cfg.T_defs, -1)
+
+
static void st_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
struct sgsn_mm_ctx *ctx = fi->priv;
@@ -33,14 +47,14 @@ static void st_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
if (require_identity_imei) {
ctx->gmm_att_req.id_type = GSM_MI_TYPE_IMEI;
- osmo_fsm_inst_state_chg(fi, ST_IDENTIY, sgsn->cfg.timers.T3370, 3370);
+ gmm_attach_fsm_state_chg(fi, ST_IDENTIY);
} else if (!strlen(ctx->imsi)) {
ctx->gmm_att_req.id_type = GSM_MI_TYPE_IMSI;
- osmo_fsm_inst_state_chg(fi, ST_IDENTIY, sgsn->cfg.timers.T3370, 3370);
+ gmm_attach_fsm_state_chg(fi, ST_IDENTIY);
} else if (require_auth)
- osmo_fsm_inst_state_chg(fi, ST_AUTH, sgsn->cfg.timers.T3360, 3360);
+ gmm_attach_fsm_state_chg(fi, ST_AUTH);
else
- osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
+ gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
}
static void st_identity_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
@@ -94,11 +108,11 @@ static void st_identity(struct osmo_fsm_inst *fi, uint32_t event, void *data)
if (type == GSM_MI_TYPE_IMEI && !strlen(ctx->imsi)) {
ctx->gmm_att_req.id_type = GSM_MI_TYPE_IMSI;
- osmo_fsm_inst_state_chg(fi, ST_IDENTIY, sgsn->cfg.timers.T3370, 3370);
+ gmm_attach_fsm_state_chg(fi, ST_IDENTIY);
} else if (require_auth)
- osmo_fsm_inst_state_chg(fi, ST_AUTH, sgsn->cfg.timers.T3360, 3360);
+ gmm_attach_fsm_state_chg(fi, ST_AUTH);
else
- osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
+ gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
}
static void st_auth_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
@@ -124,19 +138,19 @@ static void st_auth_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
switch(auth_state) {
case SGSN_AUTH_UMTS_RESYNC: /* ask the vlr for a new vector to match the simcards seq */
case SGSN_AUTH_UNKNOWN: /* the SGSN doesn know this MS */
- osmo_fsm_inst_state_chg(fi, ST_ASK_VLR, sgsn->cfg.timers.T3350, 3350);
+ gmm_attach_fsm_state_chg(fi, ST_ASK_VLR);
break;
case SGSN_AUTH_REJECTED:
/* TODO: correct GMM cause */
osmo_fsm_inst_dispatch(fi, E_REJECT, (void *) GMM_CAUSE_GPRS_NOTALLOWED);
break;
case SGSN_AUTH_ACCEPTED:
- osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
+ gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
break;
case SGSN_AUTH_AUTHENTICATE:
if (ctx->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
/* invalid key material */
- osmo_fsm_inst_state_chg(fi, ST_ASK_VLR, sgsn->cfg.timers.T3350, 3350);
+ gmm_attach_fsm_state_chg(fi, ST_ASK_VLR);
}
struct gsm_auth_tuple *at = &ctx->auth_triplet;
@@ -159,14 +173,14 @@ static void st_auth(struct osmo_fsm_inst *fi, uint32_t event, void *data)
sgsn_auth_request(ctx);
#ifdef BUILD_IU
if (ctx->ran_type == MM_CTX_T_UTRAN_Iu && !ctx->iu.ue_ctx->integrity_active)
- osmo_fsm_inst_state_chg(fi, ST_IU_SECURITY_CMD, sgsn->cfg.timers.T3350, 3350);
+ gmm_attach_fsm_state_chg(fi, ST_IU_SECURITY_CMD);
else
#endif /* BUILD_IU */
- osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
+ gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
break;
case E_AUTH_RESP_RECV_RESYNC:
if (ctx->gmm_att_req.auth_reattempt <= 1)
- osmo_fsm_inst_state_chg(fi, ST_ASK_VLR, sgsn->cfg.timers.T3350, 3350);
+ gmm_attach_fsm_state_chg(fi, ST_ASK_VLR);
else
osmo_fsm_inst_dispatch(fi, E_REJECT, (void *) GMM_CAUSE_SYNC_FAIL);
break;
@@ -234,7 +248,7 @@ static void st_ask_vlr(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch(event) {
case E_VLR_ANSWERED:
- osmo_fsm_inst_state_chg(fi, ST_AUTH, sgsn->cfg.timers.T3360, 3360);
+ gmm_attach_fsm_state_chg(fi, ST_AUTH);
break;
}
}
@@ -246,7 +260,7 @@ static void st_iu_security_cmd_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_
/* TODO: shouldn't this set always? not only when the integrity_active? */
if (ctx->iu.ue_ctx->integrity_active) {
- osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
+ gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
return;
}
@@ -259,7 +273,7 @@ static void st_iu_security_cmd(struct osmo_fsm_inst *fi, uint32_t event, void *d
{
switch(event) {
case E_IU_SECURITY_CMD_COMPLETE:
- osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
+ gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
break;
}
}
@@ -373,6 +387,7 @@ int gmm_attach_timer_cb(struct osmo_fsm_inst *fi)
{
struct sgsn_mm_ctx *ctx = fi->priv;
struct gsm_auth_tuple *at = &ctx->auth_triplet;
+ unsigned long t_secs;
ctx->num_T_exp++;
@@ -392,7 +407,9 @@ int gmm_attach_timer_cb(struct osmo_fsm_inst *fi)
break;
}
gsm48_tx_gmm_id_req(ctx, ctx->gmm_att_req.id_type);
- osmo_timer_schedule(&fi->timer, sgsn->cfg.timers.T3370, 0);
+ t_secs = osmo_tdef_get(sgsn->cfg.T_defs, 3370, OSMO_TDEF_S, -1);
+ osmo_timer_schedule(&fi->timer, t_secs, 0);
+
break;
case ST_AUTH:
/* T3360 */
@@ -401,7 +418,8 @@ int gmm_attach_timer_cb(struct osmo_fsm_inst *fi)
break;
}
gsm48_tx_gmm_auth_ciph_req(ctx, &at->vec, at->key_seq, false);
- osmo_timer_schedule(&fi->timer, sgsn->cfg.timers.T3360, 0);
+ t_secs = osmo_tdef_get(sgsn->cfg.T_defs, 3360, OSMO_TDEF_S, -1);
+ osmo_timer_schedule(&fi->timer, t_secs, 0);
break;
case ST_ACCEPT:
/* T3350 */
@@ -410,7 +428,8 @@ int gmm_attach_timer_cb(struct osmo_fsm_inst *fi)
break;
}
gsm48_tx_gmm_att_ack(ctx);
- osmo_timer_schedule(&fi->timer, sgsn->cfg.timers.T3350, 0);
+ t_secs = osmo_tdef_get(sgsn->cfg.T_defs, 3350, OSMO_TDEF_S, -1);
+ osmo_timer_schedule(&fi->timer, t_secs, 0);
break;
}
diff --git a/src/gprs/sgsn_vty.c b/src/gprs/sgsn_vty.c
index d1d53e68..ae26cbea 100644
--- a/src/gprs/sgsn_vty.c
+++ b/src/gprs/sgsn_vty.c
@@ -28,6 +28,7 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/rate_ctr.h>
+#include <osmocom/core/tdef.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/apn.h>
@@ -39,6 +40,7 @@
#include <osmocom/sgsn/vty.h>
#include <osmocom/gsupclient/gsup_client.h>
+#include <osmocom/vty/tdef_vty.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/misc.h>
@@ -88,39 +90,42 @@ const struct value_string sgsn_auth_pol_strs[] = {
#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
-#define DECLARE_TIMER(number, doc) \
- DEFUN(cfg_sgsn_T##number, \
- cfg_sgsn_T##number##_cmd, \
- "timer t" #number " <0-65535>", \
- "Configure GPRS Timers\n" \
- doc "\nTimer Value in seconds\n") \
-{ \
- int value = atoi(argv[0]); \
- \
- if (value < 0 || value > 65535) { \
- vty_out(vty, "Timer value %s out of range.%s", \
- argv[0], VTY_NEWLINE); \
- return CMD_WARNING; \
- } \
- \
- g_cfg->timers.T##number = value; \
- return CMD_SUCCESS; \
-}
-DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
-DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
-DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
-DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
-DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
+static struct osmo_tdef sgsn_T_defs[] = {
+ { .T=3312, .default_val=GSM0408_T3312_SECS, .desc="Periodic RA Update timer (s)" },
+ { .T=3313, .default_val=GSM0408_T3313_SECS, .desc="Waiting for paging response timer (s)" },
+ { .T=3314, .default_val=GSM0408_T3314_SECS, .desc="Force to STANDBY on expiry timer (s)" },
+ { .T=3316, .default_val=GSM0408_T3316_SECS, .desc="AA-Ready timer (s)" },
+ { .T=3322, .default_val=GSM0408_T3322_SECS, .desc="Detach request -> accept timer (s)" },
+ { .T=3350, .default_val=GSM0408_T3350_SECS, .desc="Waiting for ATT/RAU/TMSI_COMPL timer (s)" },
+ { .T=3360, .default_val=GSM0408_T3360_SECS, .desc="Waiting for AUTH/CIPH response timer (s)" },
+ { .T=3370, .default_val=GSM0408_T3370_SECS, .desc="Waiting for IDENTITY response timer (s)" },
+ { .T=3385, .default_val=GSM0408_T3385_SECS, .desc="Wait for ACT PDP CTX REQ timer (s)" },
+ { .T=3386, .default_val=GSM0408_T3386_SECS, .desc="Wait for MODIFY PDP CTX ACK timer (s)" },
+ { .T=3395, .default_val=GSM0408_T3395_SECS, .desc="Wait for DEACT PDP CTX ACK timer (s)" },
+ { .T=3397, .default_val=GSM0408_T3397_SECS, .desc="Wait for DEACT AA PDP CTX ACK timer (s)" },
+ {}
+};
-DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
-DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
-DECLARE_TIMER(3316, "AA-Ready timer (s)")
+DEFUN(show_timer, show_timer_cmd,
+ "show timer " OSMO_TDEF_VTY_ARG_T_OPTIONAL,
+ SHOW_STR "Show timers\n"
+ OSMO_TDEF_VTY_DOC_T)
+{
+ const char *T_arg = argc > 0 ? argv[0] : NULL;
+ return osmo_tdef_vty_show_cmd(vty, g_cfg->T_defs, T_arg, NULL);
+}
-DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
-DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
-DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
-DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
+DEFUN(cfg_sgsn_timer, cfg_sgsn_timer_cmd,
+ "timer " OSMO_TDEF_VTY_ARG_SET_OPTIONAL,
+ "Configure or show timers\n"
+ OSMO_TDEF_VTY_DOC_SET)
+{
+ /* If any arguments are missing, redirect to 'show' */
+ if (argc < 2)
+ return show_timer(self, vty, argc, argv);
+ return osmo_tdef_vty_set_cmd(vty, g_cfg->T_defs, argv);
+}
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
{
@@ -253,18 +258,7 @@ static int config_write_sgsn(struct vty *vty)
vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
- vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
- vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
- vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
- vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
- vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
- vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
- vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
- vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
- vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
- vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
- vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
- vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
+ osmo_tdef_vty_write(vty, g_cfg->T_defs, " timer ");
if (g_cfg->pcomp_rfc1144.active) {
vty_out(vty, " compression rfc1144 active slots %d%s",
@@ -1388,12 +1382,16 @@ int sgsn_vty_init(struct sgsn_config *cfg)
{
g_cfg = cfg;
+ g_cfg->T_defs = sgsn_T_defs;
+ osmo_tdefs_reset(g_cfg->T_defs);
+
install_element_ve(&show_sgsn_cmd);
//install_element_ve(&show_mmctx_tlli_cmd);
install_element_ve(&show_mmctx_imsi_cmd);
install_element_ve(&show_mmctx_all_cmd);
install_element_ve(&show_pdpctx_all_cmd);
install_element_ve(&show_subscr_cache_cmd);
+ install_element_ve(&show_timer_cmd);
install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
install_element(ENABLE_NODE, &update_subscr_create_cmd);
@@ -1433,18 +1431,7 @@ int sgsn_vty_init(struct sgsn_config *cfg)
install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
- install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
+ install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
@@ -1466,19 +1453,6 @@ int sgsn_parse_config(const char *config_file)
/* make sure sgsn_vty_init() was called before this */
OSMO_ASSERT(g_cfg);
- g_cfg->timers.T3312 = GSM0408_T3312_SECS;
- g_cfg->timers.T3322 = GSM0408_T3322_SECS;
- g_cfg->timers.T3350 = GSM0408_T3350_SECS;
- g_cfg->timers.T3360 = GSM0408_T3360_SECS;
- g_cfg->timers.T3370 = GSM0408_T3370_SECS;
- g_cfg->timers.T3313 = GSM0408_T3313_SECS;
- g_cfg->timers.T3314 = GSM0408_T3314_SECS;
- g_cfg->timers.T3316 = GSM0408_T3316_SECS;
- g_cfg->timers.T3385 = GSM0408_T3385_SECS;
- g_cfg->timers.T3386 = GSM0408_T3386_SECS;
- g_cfg->timers.T3395 = GSM0408_T3395_SECS;
- g_cfg->timers.T3397 = GSM0408_T3397_SECS;
-
rc = vty_read_config_file(config_file, NULL);
if (rc < 0) {
fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
diff --git a/tests/sgsn/sgsn_test.c b/tests/sgsn/sgsn_test.c
index 23cb4fbc..cc25d47f 100644
--- a/tests/sgsn/sgsn_test.c
+++ b/tests/sgsn/sgsn_test.c
@@ -37,6 +37,7 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/utils.h>
+#include <osmocom/vty/vty.h>
#include <stdio.h>
@@ -1646,6 +1647,10 @@ static struct log_info info = {
.num_cat = ARRAY_SIZE(gprs_categories),
};
+static struct vty_app_info vty_info = {
+ .name = "testSGSN",
+};
+
int main(int argc, char **argv)
{
void *osmo_sgsn_ctx;
@@ -1659,6 +1664,8 @@ int main(int argc, char **argv)
sgsn_rate_ctr_init();
sgsn_auth_init(sgsn);
gprs_subscr_init(sgsn);
+ vty_init(&vty_info);
+ sgsn_vty_init(&sgsn->cfg);
test_llme();
test_subscriber();