Project

General

Profile

Bug #3296 ยป lchan_fsm.c

laforge, 05/28/2018 02:44 PM

 
1
#include <osmocom/core/fsm.h>
2

    
3
enum lchan_fsm_states {
4
	/* Administratively disableD */
5
	ST_DISABLED,
6
	/* Inactive; waiting to be allocated */
7
	ST_INACTIVE,
8
	/* waiting for RSL CHAN ACT ACK from BTS */
9
	ST_WAIT_ACT_ACK,
10
	/* active, i.e. channel in use at BTS/MS */
11
	ST_ACTIVE,
12
	/* waiting for RSL RF CHAN REL ACK from BTS */
13
	ST_WAIT_DEACT_ACK,
14

    
15
	/* waiting for RSL CHAN ACT ACK from BTS for PDCH */
16
	ST_WAIT_ACT_PDCH_ACK,
17
	/* active in PDCH mode for GPRS/EGPRS */
18
	ST_ACTIVE_PDCH,
19
	/* waiting for RSL CHAN ACT ACK from BTS for PDCH */
20
	ST_WAIT_DEACT_PDCH_ACK,
21
};
22

    
23
enum lchan_fsm_timer {
24
	LCHAN_T_ACT,
25
	LCHAN_T_DEACT,
26
};
27

    
28
enum lchan_fsm_event {
29
	/* OML tells us this lchan is enabled (->INACTIVE) */
30
	LCHAN_EV_ENABLE,
31
	/* OML tells us to disable this chnanel (->DISABLED) */
32
	LCHAN_EV_DISABLE,
33
	/* BSC requests channel activation */
34
	LCHAN_EV_ACTIVATE,
35
	/* BSC requests channel deactivation */
36
	LCHAN_EV_DEACTIVATE,
37

    
38
	/* RSL DChan ACT/DEACT Events */
39
	LCHAN_EV_CHAN_ACT_ACK,
40
	LCHAN_EV_CHAN_ACT_NACK,
41
	LCHAN_EV_CHAN_REL_ACK,
42
	LCHAN_EV_CHAN_REL_NACK,
43

    
44
	/* RSL RLL Message */
45
	LCHAN_EV_RLL_FROM_BTS,
46
	LCHAN_EV_RLL_FROM_BSC,
47
	/* RSL DCHAN Message */
48
	LCHAN_EV_DCHAN_FROM_BTS,
49
	LCHAN_EV_DCHAN_FROM_BSC,
50
};
51

    
52
static void lchan_fsm_disabled(struct osmo_fsm_inst *fi, uint32_t event, void *data)
53
{
54
	struct gsm_lchan *lchan = fi->priv;
55

    
56
	switch (event) {
57
	case LCHAN_EV_ENABLE:
58
		osmo_fsm_inst_state_chg(fi, ST_INACTIVE, 0, 0);
59
		break;
60
	}
61
}
62

    
63
static void lchan_fsm_inactive(struct osmo_fsm_inst *fi, uint32_t event, void *data)
64
{
65
	struct gsm_lchan *lchan = fi->priv;
66

    
67
	switch (event) {
68
	case LCHAN_EV_DISABLE:
69
		osmo_fsm_inst_state_chg(fi, ST_DISABLED, 0, 0);
70
		break;
71
	case LCHAN_EV_ACTIVATE:
72
		/* Send RSL RF CHAN ACT */
73
		rsl_chan_activate_lchan(lchan, act_type, ho_ref);
74
		osmo_fsm_inst_state_chg(fi, ST_WAIT_ACT_ACK, 4, LCHAN_T_ACT);
75
		break;
76
	}
77
}
78

    
79
static void lchan_fsm_wait_act_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
80
{
81
	struct gsm_lchan *lchan = fi->priv;
82
	struct tlv_parsed *tp = data;
83

    
84
	switch (event) {
85
	case LCHAN_EV_CHAN_ACT_ACK:
86
		osmo_fsm_inst_state_chg(fi, ST_ACTIVE, 0, 0);
87
		if (lchan->rqd_ref) {
88
			rsl_send_imm_assignment(lchan);
89
			talloc_free(lchan->rqd_ref);
90
			lchan->rqd_ref = NULL;
91
			lchan->rqd_ta = 0;
92
		}
93
		send_lchan_signal(S_LCHAN_ACTIVATE_ACK, lchan, NULL);
94
		break;
95
	case LCHAN_EV_CHAN_ACT_NACK:
96
		rate_ctr_inc(&lchan->ts->trx->bts->bts_ctrs->ctr[BTS_CTR_CHAN_ACT_NACK]);
97
		if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
98
			const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
99
			/* print cause */
100
			if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC) {
101
				/* rsl_lchan_mark_broken(msg->lchan, "NACK on activation"); */
102
			} else {
103
				rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE);
104
			}
105
		} else {
106
			/*rsl_lchan_mark_broken(msg->lchan, "NACK on activation no IE");*/
107
		}
108
		send_lchan_signal(S_LCHAN_ACTIVATE_NACK, lchan, NULL);
109
		break;
110
	}
111
}
112

    
113
static void lchan_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data)
114
{
115
	struct gsm_lchan *lchan = fi->priv;
116

    
117
	switch (event) {
118
	case LCHAN_EV_DEACTIVATE:
119
		/* Send RSL RF CHAN REL */
120
		rsl_rf_chan_release(lchan, error, deact_sacch;
121
		osmo_fsm_inst_state_chg(fi, ST_WAIT_DEACT_ACK, 4, LCHAN_T_DEACT);
122
		break;
123
	case LCHAN_EV_RLL_FROM_BTS:
124
		/* forward from BTS to MSC */
125
		break;
126
	case LCHAN_EV_RLL_FROM_BSC:
127
		/* forward from MSC/BSC to BTS */
128
		break;
129
	case LCHAN_EV_DCHAN_FROM_BTS:
130
		/* forward from BTS to MSC */
131
		break;
132
	case LCHAN_EV_DCHAN_FROM_BSC:
133
		/* forward from MSC/BSC to BTS */
134
		break;
135
	}
136
}
137

    
138
static void lchan_fsm_wait_deact_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
139
{
140
	struct gsm_lchan *lchan = fi->priv;
141

    
142
	switch (event) {
143
	case LCHAN_EV_CHAN_REL_ACK:
144
		/* FIXME: check if this is a dynamic channel + activate as PDCH? */
145
		osmo_fsm_inst_state_chg(fi, ST_INACTIVE, 0, 0);
146
		break;
147
	case LCHAN_EV_CHAN_REL_NACK:
148
		break;
149
	}
150
}
151

    
152
static void lchan_fsm_wait_act_pdch_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
153
{
154
	struct gsm_lchan *lchan = fi->priv;
155

    
156
	switch (event) {
157
	case LCHAN_EV_CHAN_ACT_ACK:
158
		osmo_fsm_inst_state_chg(fi, ST_ACTIVE_PDCH, 0, 0);
159
		break;
160
	case LCHAN_EV_CHAN_ACT_NACK:
161
		break;
162
	}
163
}
164

    
165
static void lchan_fsm_active_pdch(struct osmo_fsm_inst *fi, uint32_t event, void *data)
166
{
167
	struct gsm_lchan *lchan = fi->priv;
168

    
169
	switch (event) {
170
	case LCHAN_EV_DEACTIVATE:
171
		rsl_rf_chan_release(lchan, 0, 0);
172
		osmo_fsm_inst_state_chg(fi, ST_WAIT_DEACT_PDCH_ACK, 0, 0);
173
		break;
174
	case LCHAN_EV_ACTIVATE: /* transition to non-PDCH mode */
175
		foo = 1;
176
		osmo_fsm_inst_state_chg(fi, ST_WAIT_DEACT_PDCH_ACK, 0, 0);
177
		break;
178
	}
179
}
180

    
181
static void lchan_fsm_wait_deact_pdch_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
182
{
183
	struct gsm_lchan *lchan = fi->priv;
184

    
185
	switch (event) {
186
	case LCHAN_EV_CHAN_REL_ACK:
187
		osmo_fsm_inst_state_chg(fi, ST_INACTIVE, 0, 0);
188
		/* immediately re-activate as desired type, if pending */
189
		if (foo)
190
			osmo_fsm_inst_dispatch_event(fi, LCHAN_EV_ACTIVATE, NULL);
191
		break;
192
	case LCHAN_EV_CHAN_REL_NACK:
193
		break;
194
	}
195
}
196

    
197

    
198
static int lchan_fsm_timer_cb(struct osmo_fsm_inst *fi)
199
{
200
	struct gsm_lchan *lchan = fi->priv;
201

    
202
	switch (fi->T) {
203
	case LCHAN_T_ACT:
204
		break;
205
	case LCHAN_T_DEACT:
206
		break;
207
	}
208
}
209

    
210
const struct osmo_fsm_state lchan_fsm_stats[] = {
211
	[ST_DISABLED] = {
212
		.in_event_mask = S(LCHAN_EV_ENABLE),
213
		.out_state_mask = S(ST_INACTIVE),
214
		.name = "DISABLED",
215
		.action = lchan_fsm_disabled,
216
	},
217
	[ST_INACTIVE] = {
218
		.in_event_mask = S(LCHAN_EV_ACTIVATE) |
219
				 S(LCHAN_EV_DISABLE),
220
		.out_state_mask = S(ST_WAIT_ACT_ACK) |
221
				  S(ST_WAIT_ACT_PDCH_ACK),
222
		.name = "INACTIVE",
223
		.action = lchan_fsm_inactive,
224
	},
225
	[ST_WAIT_ACT_ACK] = {
226
		.in_event_mask = S(LCHAN_EV_CHAN_ACT_ACK) |
227
				 S(LCHAN_EV_CHAN_ACT_NACK),
228
		.out_state_mask = S(ST_INACTIVE) | S(ST_ACTIVE),
229
		.name = "WAIT_ACT_ACK",
230
		.action = lchan_fsm_wait_act_ack,
231
	},
232
	[ST_ACTIVE] = {
233
		.in_event_mask = S(LCHAN_EV_DEACTIVATE) |
234
				 S(LCHAN_EV_RLL_FROM_BTS) |
235
				 S(LCHAN_EV_RLL_FROM_BSC) |
236
				 S(LCHAN_EV_DCHAN_FROM_BTS) |
237
				 S(LCHAN_EV_DCHAN_FROM_BSC),
238
		.out_state_mask = S(ST_WAIT_DEACT_ACK),
239
		.name = "ACTIVE",
240
		.action = lchan_fsm_active,
241
	},
242
	[ST_WAIT_DEACT_ACK] = {
243
		.in_event_mask = S(LCHAN_EV_CHAN_REL_ACK) |
244
				 S(LCHAN_EV_CHAN_REL_NACK),
245
		.out_state_mask = S(ST_INACTIVE),
246
		.name = "WAIT_DEACT_ACK",
247
		.action = lchan_fsm_wait_deact_ack,
248
	},
249

    
250
	[ST_WAIT_ACT_PDCH_ACK] = {
251
		.in_event_mask = S(LCHAN_EV_CHAN_ACT_ACK) |
252
				 S(LCHAN_EV_CHAN_ACT_NACK),
253
		.out_state_mask = S(ST_INACTIVE) | S(ST_ACTIVE_PDCH),
254
		.name = "WAIT_ACT_PDCH_ACK",
255
		.action = lchan_fsm_wait_act_pdch_ack,
256
	},
257
	[ST_ACTIVE_PDCH] = {
258
		.in_event_mask = S(LCHAN_EV_DEACTIVATE) |
259
				 S(LCHAN_EV_ACTIVATE),
260
		.out_state_mask = S(ST_WAIT_DEACT_PDCH_ACK),
261
		.name = "ACTIVE_PDCH",
262
		.action = lchan_fsm_active_pdch,
263
	},
264
	[ST_WAIT_DEACT_PDCH_ACK] = {
265
		.in_event_mask = S(LCHAN_EV_CHAN_REL_ACK) |
266
				 S(LCHAN_EV_CHAN_REL_NACK),
267
		.out_state_mask = S(ST_INACTIVE),
268
		.name = "WAIT_DEACT_PDCH_ACK",
269
		.action = lchan_fsm_wait_deact_pdch_ack,
270
	},
271

    
272

    
273
};
274

    
275
struct osmo_fsm lchan_fsm = {
276
	.name = "LCHAN",
277
	.states = lchan_fsm_states,
278
	.num_states = ARRAY_SIZE(lchan_fsm_states),
279
	.timer_cb = lchan_fsm_timer_cb,
280
	.log_subsys = DRSL,
281
	.event_names = lchan_fsm_event_names,
282
};
283

    
284
struct osmo_fsm_inst *lchan_fsm_inst_alloc(struct gsm_lchan *lchan, int log_level)
285
{
286
	return osmo_fsm_inst_alloc(&lchan_fsm, lchan->ts->trx, lchan, log_level, id);
287
}
    (1-1/1)
    Add picture from clipboard (Maximum size: 48.8 MB)