blob: 811f0c2f43b32fb5ad3c0a45f5ce22dea5227093 [file] [log] [blame]
Pau Espin Pedrol02514bc2019-08-30 16:14:22 +02001#include <osmocom/core/tdef.h>
2
3#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
Alexander Couzens68880212019-09-10 16:32:05 +02004#include <osmocom/sgsn/gprs_llc.h>
Pau Espin Pedrol02514bc2019-08-30 16:14:22 +02005
6#include <osmocom/sgsn/debug.h>
7#include <osmocom/sgsn/sgsn.h>
8
9#define X(s) (1 << (s))
10
11static const struct osmo_tdef_state_timeout mm_state_gb_fsm_timeouts[32] = {
12 [ST_MM_IDLE] = { },
13 [ST_MM_READY] = { .T=3314 },
14 [ST_MM_STANDBY] = { },
15};
16
17#define mm_state_gb_fsm_state_chg(fi, NEXT_STATE) \
18 osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, mm_state_gb_fsm_timeouts, sgsn->cfg.T_defs, -1)
19
Alexander Couzens68880212019-09-10 16:32:05 +020020static void st_mm_idle_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) {
21 struct sgsn_mm_ctx *ctx = fi->priv;
22
Alexander Couzens4c7609a2019-09-11 03:00:47 +020023 /* FIXME: remove this timer when RAU has it's own fsm */
24 if (ctx->T == 3350 && osmo_timer_pending(&ctx->timer))
25 osmo_timer_del(&ctx->timer);
26
Alexander Couzens68880212019-09-10 16:32:05 +020027 if (ctx->gb.llme) {
28 gprs_llgmm_unassign(ctx->gb.llme);
29 ctx->gb.llme = NULL;
30 }
31}
32
Pau Espin Pedrol02514bc2019-08-30 16:14:22 +020033static void st_mm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
34{
35 switch(event) {
36 case E_MM_GPRS_ATTACH:
37 mm_state_gb_fsm_state_chg(fi, ST_MM_READY);
38 break;
39 case E_MM_PDU_RECEPTION:
40 break;
41 }
42}
43
44static void st_mm_ready(struct osmo_fsm_inst *fi, uint32_t event, void *data)
45{
46 unsigned long t_secs;
47
48 switch(event) {
49 case E_MM_READY_TIMER_EXPIRY:
Pau Espin Pedrol02514bc2019-08-30 16:14:22 +020050 mm_state_gb_fsm_state_chg(fi, ST_MM_STANDBY);
51 break;
Alexander Couzens12235312019-09-17 17:44:14 +020052 case E_MM_IMPLICIT_DETACH:
53 mm_state_gb_fsm_state_chg(fi, ST_MM_IDLE);
54 break;
Pau Espin Pedrol02514bc2019-08-30 16:14:22 +020055 case E_MM_PDU_RECEPTION:
56 /* RE-arm the READY timer upon receival of Gb PDUs */
57 t_secs = osmo_tdef_get(sgsn->cfg.T_defs, 3314, OSMO_TDEF_S, -1);
58 osmo_timer_schedule(&fi->timer, t_secs, 0);
59 break;
60 case E_MM_RA_UPDATE:
61 break;
62 }
63}
64
65static void st_mm_standby(struct osmo_fsm_inst *fi, uint32_t event, void *data)
66{
67 switch(event) {
68 case E_MM_PDU_RECEPTION:
69 mm_state_gb_fsm_state_chg(fi, ST_MM_READY);
70 break;
71 }
72}
73
74static struct osmo_fsm_state mm_state_gb_fsm_states[] = {
75 [ST_MM_IDLE] = {
76 .in_event_mask = X(E_MM_GPRS_ATTACH) | X(E_MM_PDU_RECEPTION),
77 .out_state_mask = X(ST_MM_READY),
Alexander Couzens68880212019-09-10 16:32:05 +020078 .onenter = st_mm_idle_on_enter,
Pau Espin Pedrol02514bc2019-08-30 16:14:22 +020079 .name = "Idle",
80 .action = st_mm_idle,
81 },
82 [ST_MM_READY] = {
83 .in_event_mask = X(E_MM_READY_TIMER_EXPIRY) | X(E_MM_RA_UPDATE) | X(E_MM_IMPLICIT_DETACH) | X(E_MM_PDU_RECEPTION),
84 .out_state_mask = X(ST_MM_IDLE) | X(ST_MM_STANDBY),
85 .name = "Ready",
86 .action = st_mm_ready,
87 },
88 [ST_MM_STANDBY] = {
89 .in_event_mask = X(E_MM_PDU_RECEPTION),
90 .out_state_mask = X(ST_MM_IDLE) | X(ST_MM_READY),
91 .name = "Standby",
92 .action = st_mm_standby,
93 },
94};
95
96const struct value_string mm_state_gb_fsm_event_names[] = {
97 OSMO_VALUE_STRING(E_MM_GPRS_ATTACH),
98 OSMO_VALUE_STRING(E_MM_PDU_RECEPTION),
99 OSMO_VALUE_STRING(E_MM_IMPLICIT_DETACH),
100 OSMO_VALUE_STRING(E_MM_READY_TIMER_EXPIRY),
101 OSMO_VALUE_STRING(E_MM_RA_UPDATE),
102 { 0, NULL }
103};
104
105int mm_state_gb_fsm_timer_cb(struct osmo_fsm_inst *fi)
106{
107 switch(fi->state) {
108 case ST_MM_READY:
109 /* timer for mm state. state=READY: T3314 (aka TS 23.060 "READY timer") */
110 osmo_fsm_inst_dispatch(fi, E_MM_READY_TIMER_EXPIRY, NULL);
111 break;
112 }
113
114 return 0;
115}
116
117struct osmo_fsm mm_state_gb_fsm = {
118 .name = "MM_STATE_Gb",
119 .states = mm_state_gb_fsm_states,
120 .num_states = ARRAY_SIZE(mm_state_gb_fsm_states),
121 .event_names = mm_state_gb_fsm_event_names,
122 .log_subsys = DMM,
123 .timer_cb = mm_state_gb_fsm_timer_cb,
124};
125
126static __attribute__((constructor)) void mm_state_gb_fsm_init(void)
127{
Harald Weltea868e172019-12-01 13:23:53 +0100128 OSMO_ASSERT(osmo_fsm_register(&mm_state_gb_fsm) == 0);
Pau Espin Pedrol02514bc2019-08-30 16:14:22 +0200129}