blob: 2056540db68c1e231814342e767415a4be3e6668 [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>
4
5#include <osmocom/sgsn/debug.h>
6#include <osmocom/sgsn/sgsn.h>
7
8#define X(s) (1 << (s))
9
10static const struct osmo_tdef_state_timeout mm_state_gb_fsm_timeouts[32] = {
11 [ST_MM_IDLE] = { },
12 [ST_MM_READY] = { .T=3314 },
13 [ST_MM_STANDBY] = { },
14};
15
16#define mm_state_gb_fsm_state_chg(fi, NEXT_STATE) \
17 osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, mm_state_gb_fsm_timeouts, sgsn->cfg.T_defs, -1)
18
19static void st_mm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
20{
21 switch(event) {
22 case E_MM_GPRS_ATTACH:
23 mm_state_gb_fsm_state_chg(fi, ST_MM_READY);
24 break;
25 case E_MM_PDU_RECEPTION:
26 break;
27 }
28}
29
30static void st_mm_ready(struct osmo_fsm_inst *fi, uint32_t event, void *data)
31{
32 unsigned long t_secs;
33
34 switch(event) {
35 case E_MM_READY_TIMER_EXPIRY:
36 case E_MM_IMPLICIT_DETACH:
37 mm_state_gb_fsm_state_chg(fi, ST_MM_STANDBY);
38 break;
39 case E_MM_PDU_RECEPTION:
40 /* RE-arm the READY timer upon receival of Gb PDUs */
41 t_secs = osmo_tdef_get(sgsn->cfg.T_defs, 3314, OSMO_TDEF_S, -1);
42 osmo_timer_schedule(&fi->timer, t_secs, 0);
43 break;
44 case E_MM_RA_UPDATE:
45 break;
46 }
47}
48
49static void st_mm_standby(struct osmo_fsm_inst *fi, uint32_t event, void *data)
50{
51 switch(event) {
52 case E_MM_PDU_RECEPTION:
53 mm_state_gb_fsm_state_chg(fi, ST_MM_READY);
54 break;
55 }
56}
57
58static struct osmo_fsm_state mm_state_gb_fsm_states[] = {
59 [ST_MM_IDLE] = {
60 .in_event_mask = X(E_MM_GPRS_ATTACH) | X(E_MM_PDU_RECEPTION),
61 .out_state_mask = X(ST_MM_READY),
62 .name = "Idle",
63 .action = st_mm_idle,
64 },
65 [ST_MM_READY] = {
66 .in_event_mask = X(E_MM_READY_TIMER_EXPIRY) | X(E_MM_RA_UPDATE) | X(E_MM_IMPLICIT_DETACH) | X(E_MM_PDU_RECEPTION),
67 .out_state_mask = X(ST_MM_IDLE) | X(ST_MM_STANDBY),
68 .name = "Ready",
69 .action = st_mm_ready,
70 },
71 [ST_MM_STANDBY] = {
72 .in_event_mask = X(E_MM_PDU_RECEPTION),
73 .out_state_mask = X(ST_MM_IDLE) | X(ST_MM_READY),
74 .name = "Standby",
75 .action = st_mm_standby,
76 },
77};
78
79const struct value_string mm_state_gb_fsm_event_names[] = {
80 OSMO_VALUE_STRING(E_MM_GPRS_ATTACH),
81 OSMO_VALUE_STRING(E_MM_PDU_RECEPTION),
82 OSMO_VALUE_STRING(E_MM_IMPLICIT_DETACH),
83 OSMO_VALUE_STRING(E_MM_READY_TIMER_EXPIRY),
84 OSMO_VALUE_STRING(E_MM_RA_UPDATE),
85 { 0, NULL }
86};
87
88int mm_state_gb_fsm_timer_cb(struct osmo_fsm_inst *fi)
89{
90 switch(fi->state) {
91 case ST_MM_READY:
92 /* timer for mm state. state=READY: T3314 (aka TS 23.060 "READY timer") */
93 osmo_fsm_inst_dispatch(fi, E_MM_READY_TIMER_EXPIRY, NULL);
94 break;
95 }
96
97 return 0;
98}
99
100struct osmo_fsm mm_state_gb_fsm = {
101 .name = "MM_STATE_Gb",
102 .states = mm_state_gb_fsm_states,
103 .num_states = ARRAY_SIZE(mm_state_gb_fsm_states),
104 .event_names = mm_state_gb_fsm_event_names,
105 .log_subsys = DMM,
106 .timer_cb = mm_state_gb_fsm_timer_cb,
107};
108
109static __attribute__((constructor)) void mm_state_gb_fsm_init(void)
110{
111 osmo_fsm_register(&mm_state_gb_fsm);
112}