comparison src/g23m-gprs/sm/sm_dispatcher.c @ 1:fa8dc04885d8

src/g23m-*: import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:25:50 +0000
parents
children
comparison
equal deleted inserted replaced
0:4e78acac3d88 1:fa8dc04885d8
1 /*----------------------------------------------------------------------------
2 | Project : 3G PS
3 | Module : SM
4 +-----------------------------------------------------------------------------
5 | Copyright 2003 Texas Instruments.
6 | All rights reserved.
7 |
8 | This file is confidential and a trade secret of Texas
9 | Instruments .
10 | The receipt of or possession of this file does not convey
11 | any rights to reproduce or disclose its contents or to
12 | manufacture, use, or sell anything it may describe, in
13 | whole, or in part, without the specific written consent of
14 | Texas Instruments.
15 +-----------------------------------------------------------------------------
16 | Purpose: This module implements the process dispatcher
17 | for the Session Management (SM) entity.
18 | For design details, see:
19 | 8010.908 SM Detailed Specification
20 +---------------------------------------------------------------------------*/
21
22 /*==== DECLARATION CONTROL =================================================*/
23
24 /*==== INCLUDES =============================================================*/
25
26 #include "sm.h"
27 #include "sm_sequencer.h"
28
29 #include "sm_network_control.h"
30 #include "sm_aci_output_handler.h"
31 #include "sm_timer_handler.h"
32
33 #include "sm_dispatcher.h"
34
35 /*==== CONSTS ===============================================================*/
36
37 /*==== TYPES ================================================================*/
38
39 /*==== LOCALS ===============================================================*/
40
41 /*==== PRIVATE FUNCTIONS ====================================================*/
42
43 /*
44 +------------------------------------------------------------------------------
45 | Function : sm_disp_allocate_context
46 +------------------------------------------------------------------------------
47 | Description : Allocate memory for a context data structure and initialize
48 | memory and state machines. Returns address of data structure.
49 |
50 | Parameters : nsapi - NSAPI of context to allocate
51 +------------------------------------------------------------------------------
52 */
53 /*@null@*/ /*@only@*/static struct T_SM_CONTEXT_DATA *
54 sm_disp_allocate_context(int /*@alt U8@*/ nsapi)
55 {
56 struct T_SM_CONTEXT_DATA *context;
57
58 context = sm_allocate_context_data();
59
60 if (context != NULL) {
61 memset(context, 0, sizeof(struct T_SM_CONTEXT_DATA));
62
63 context->nsapi = nsapi;
64
65 sm_context_control_init (context);
66 sm_context_deactivate_control_init(context);
67 sm_network_control_init (context);
68 sm_user_plane_control_init (context);
69 }
70
71 return context;
72 }
73
74 /*==== PUBLIC FUNCTIONS =====================================================*/
75
76 /*
77 +------------------------------------------------------------------------------
78 | Function : sm_disp_smreg_pdp_activate_req
79 +------------------------------------------------------------------------------
80 | Description : Dispatch SMREG_PDP_ACTIVATE_REQ
81 |
82 | Parameters : prim - received primitive
83 +------------------------------------------------------------------------------
84 */
85 void sm_disp_smreg_pdp_activate_req(T_SMREG_PDP_ACTIVATE_REQ *prim)
86 {
87 struct T_SM_CONTEXT_DATA *context;
88 T_CAUSE_ps_cause cause;
89 #ifdef DEBUG_VERBOSE
90 (void)TRACE_FUNCTION("sm_disp_smreg_pdp_activate_req");
91 #endif
92
93
94 if (!sm_is_attached() OR
95 (sm_is_suspended() AND
96 (sm_data.sm_suspend_cause EQ CAUSE_MM_LIMITED_SERVICE OR
97 sm_data.sm_suspend_cause EQ CAUSE_MM_NO_SERVICE)))
98 {
99 /*In case of limited service or no service, where GPRS is not present,
100 SM should reject the request immediately T3380 rule is not followed.*/
101 (void)TRACE_ERROR("PDP Activation rejected - limited service or no service. ");
102
103 cause.ctrl_value = CAUSE_is_from_nwsm;
104 cause.value.sm_cause = (U16)CAUSE_NWSM_ACTIVATE_REJECTED_UNSPECIFIED;
105 send_smreg_pdp_activate_rej(prim->nsapi, &cause);
106 return;
107 }
108
109
110 /* If context was MT activated, context data already exists for the TI. */
111 if (prim->ti != (U8)SM_TI_NONE) {
112 context = sm_extract_mt_context_data(prim->ti);
113
114 if (context == NULL) {
115 (void)TRACE_ERROR("Unable to find data structure allocated by MT activation request!");
116
117 cause.ctrl_value = CAUSE_is_from_nwsm;
118 cause.value.sm_cause = (U16)CAUSE_NWSM_INVALID_TI;
119 send_smreg_pdp_activate_rej(prim->nsapi, &cause);
120 return;
121 } else {
122 context->nsapi = prim->nsapi;
123 }
124 TRACE_ASSERT(context != NULL);
125 } else {
126 if (sm_get_context_data_from_nsapi(prim->nsapi) != NULL) {
127 /* Context already exists: Reject */
128 (void)TRACE_EVENT_P1("ERROR: Context already activated on NSAPI %d; "
129 "activation rejected...", (int)prim->nsapi);
130 cause.ctrl_value = CAUSE_is_from_nwsm;
131 cause.value.sm_cause = (U16)CAUSE_NWSM_NSAPI_IN_USE;
132 send_smreg_pdp_activate_rej(prim->nsapi, &cause);
133 return;
134 }
135 /* MO activation: Allocate new structure */
136 context = sm_disp_allocate_context(prim->nsapi);
137
138 if (context == NULL) {
139 (void)TRACE_ERROR("Unable to allocate data structure for new context!");
140 return;
141 }
142 }
143
144 /*If this is not done comp params will not be passed to UPM*/
145 if ( (prim->comp_params.hcomp != NAS_HCOMP_OFF) ||
146 (prim->comp_params.dcomp != NAS_DCOMP_OFF) )
147 {
148 (void)TRACE_EVENT("Compression parameters included ");
149 context->flags |= (U8)SM_CONTEXT_FLAG_COMP_PARAMS;
150 if(prim->comp_params.msid == 0){
151 prim->comp_params.msid = 16;
152 }
153 } else {
154 (void)TRACE_EVENT("Compression parameters not included ");
155 }
156
157 /* Set SM_CONTEXT_FLAG_STARTED_DURING_SUSPEND flag according to suspend status */
158 sm_set_started_during_suspend(context);
159
160 sm_assign_context_data_to_nsapi(context, prim->nsapi);
161
162 context = sm_get_context_data_from_nsapi(prim->nsapi);
163
164 sm_context_control(context, SM_P_SMREG_PDP_ACTIVATE_REQ, prim);
165 }
166
167 /*
168 +------------------------------------------------------------------------------
169 | Function : sm_disp_smreg_pdp_activate_sec_req
170 +------------------------------------------------------------------------------
171 | Description : Dispatch SMREG_PDP_ACTIVATE_SEC_REQ
172 |
173 | Parameters : prim - received primitive
174 +------------------------------------------------------------------------------
175 */
176 void sm_disp_smreg_pdp_activate_sec_req(T_SMREG_PDP_ACTIVATE_SEC_REQ *prim)
177 {
178 struct T_SM_CONTEXT_DATA *context;
179 T_CAUSE_ps_cause cause;
180 #ifdef DEBUG_VERBOSE
181 (void)TRACE_FUNCTION("sm_disp_smreg_pdp_activate_req");
182 #endif
183
184 if (sm_get_context_data_from_nsapi(prim->nsapi) != NULL) {
185 /* Context already exists: Reject */
186 (void)TRACE_EVENT_P1("ERROR: Context already activated on NSAPI %d; "
187 "activation rejected...", (int)prim->nsapi);
188 cause.ctrl_value = CAUSE_is_from_nwsm;
189 cause.value.sm_cause = (U16)CAUSE_NWSM_NSAPI_IN_USE;
190 send_smreg_pdp_activate_sec_rej(prim->nsapi, &cause);
191 return;
192 }
193
194 if (sm_get_current_nw_release() == PS_SGSN_98_OLDER) {
195 /* Secondary context activation is an R99-only procedure: Fail when in pre-R99! */
196 (void)TRACE_ERROR("R99 procedure rejected while active in pre-R99 network!");
197 cause.ctrl_value = CAUSE_is_from_sm;
198 cause.value.sm_cause = (U16)CAUSE_SM_R99_PROCEDURE_REJECTED_IN_R97;
199 send_smreg_pdp_activate_sec_rej(prim->nsapi, &cause);
200 return;
201 }
202
203 if (sm_get_context_data_from_nsapi(prim->pri_nsapi) == NULL) {
204 (void)TRACE_ERROR("sm_disp_smreg_pdp_activate_req: Primary context referenced in primitive does not exist!");
205 cause.ctrl_value = CAUSE_is_from_nwsm;
206 cause.value.sm_cause = (U16)CAUSE_NWSM_UNKNOWN_LINKED_TI;
207 send_smreg_pdp_activate_sec_rej(prim->nsapi, &cause);
208 return;
209 }
210
211 /* Allocate new context data structure */
212 context = sm_disp_allocate_context(prim->nsapi);
213
214 if (context == NULL) {
215 (void)TRACE_ERROR("Unable to allocate data structure for new context!");
216 return;
217 }
218
219 sm_set_secondary(context);
220 /* Set SM_CONTEXT_FLAG_STARTED_DURING_SUSPEND flag according to suspend status */
221 sm_set_started_during_suspend(context);
222
223 sm_assign_context_data_to_nsapi(context, prim->nsapi);
224
225 context = sm_get_context_data_from_nsapi(prim->nsapi);
226
227 sm_context_control(context, SM_P_SMREG_PDP_ACTIVATE_SEC_REQ, prim);
228 }
229
230 /*
231 +------------------------------------------------------------------------------
232 | Function : sm_disp_smreg_pdp_deactivate_req
233 +------------------------------------------------------------------------------
234 | Description : Dispatch SMREG_PDP_DEACTIVATE_REQ
235 |
236 | Parameters : prim - received primitive
237 +------------------------------------------------------------------------------
238 */
239 void sm_disp_smreg_pdp_activate_rej_res(T_SMREG_PDP_ACTIVATE_REJ_RES *prim)
240 {
241 struct T_SM_CONTEXT_DATA *context;
242 #ifdef DEBUG_VERBOSE
243 (void)TRACE_FUNCTION("sm_disp_smreg_pdp_activate_rej_res");
244 #endif
245
246 /* Context was MT activated, context data already exists for the TI. */
247 context = sm_extract_mt_context_data(prim->ti);
248
249 if (context == NULL) {
250 (void)TRACE_ERROR("Unable to find data structure allocated by MT activation request!");
251 return;
252 }
253
254 sm_context_control(context, SM_P_SMREG_PDP_ACTIVATE_REJ_RES, prim);
255
256 /* Free context data */
257 sm_free_context_data(context);
258 }
259
260 /*
261 +------------------------------------------------------------------------------
262 | Function : sm_disp_smreg_pdp_deactivate_req
263 +------------------------------------------------------------------------------
264 | Description : Dispatch SMREG_PDP_DEACTIVATE_REQ
265 |
266 | Parameters : prim - received primitive
267 +------------------------------------------------------------------------------
268 */
269 void sm_disp_smreg_pdp_deactivate_req(T_SMREG_PDP_DEACTIVATE_REQ *prim)
270 {
271 #ifdef DEBUG_VERBOSE
272 (void)TRACE_FUNCTION("sm_disp_smreg_pdp_deactivate_req");
273 #endif
274
275 /* Forward to Sequencer */
276 sm_sequencer(SM_P_SMREG_PDP_DEACTIVATE_REQ, prim);
277 }
278
279 /*
280 +------------------------------------------------------------------------------
281 | Function : sm_disp_smreg_pdp_modify_req
282 +------------------------------------------------------------------------------
283 | Description : Dispatch SMREG_PDP_MODIFY_REQ
284 |
285 | Parameters : prim - received primitive
286 +------------------------------------------------------------------------------
287 */
288 void sm_disp_smreg_pdp_modify_req(T_SMREG_PDP_MODIFY_REQ *prim)
289 {
290 struct T_SM_CONTEXT_DATA *context;
291 #ifdef DEBUG_VERBOSE
292 (void)TRACE_FUNCTION("sm_disp_smreg_pdp_modify_req");
293 #endif
294
295 context = sm_get_context_data_from_nsapi(prim->nsapi);
296
297 if (context == NULL) {
298 T_CAUSE_ps_cause cause;
299
300 (void)TRACE_ERROR("Non-existing context!");
301
302 cause.ctrl_value = CAUSE_is_from_sm;
303 cause.value.sm_cause = (U16)CAUSE_SM_INVALID_NSAPI;
304 send_smreg_pdp_modify_rej(prim->nsapi, &cause);
305 } else if (sm_get_current_nw_release() == PS_SGSN_98_OLDER) {
306 /* MO Modify is an R99-only procedure: Fail when in pre-R99! */
307 T_CAUSE_ps_cause cause;
308
309 (void)TRACE_ERROR("R99 procedure rejected while active in pre-R99 network!");
310 cause.ctrl_value = CAUSE_is_from_sm;
311 cause.value.sm_cause = (U16)CAUSE_SM_R99_PROCEDURE_REJECTED_IN_R97;
312 send_smreg_pdp_modify_rej(context->nsapi, &cause);
313 } else { /* context != NULL */
314 /* Set SM_CONTEXT_FLAG_STARTED_DURING_SUSPEND flag according to suspend status */
315 sm_set_started_during_suspend(context);
316
317 /* Forward to Context Control */
318 sm_context_control(context, SM_P_SMREG_PDP_MODIFY_REQ, prim);
319 }
320 }
321
322 /*
323 +------------------------------------------------------------------------------
324 | Function : sm_disp_sm_activate_res
325 +------------------------------------------------------------------------------
326 | Description : Dispatch SM_ACTIVATE_RES
327 |
328 | Parameters : prim - received primitive
329 +------------------------------------------------------------------------------
330 */
331 void sm_disp_sm_activate_res(T_SM_ACTIVATE_RES *prim)
332 {
333 struct T_SM_CONTEXT_DATA *context;
334 #ifdef DEBUG_VERBOSE
335 (void)TRACE_FUNCTION("sm_disp_sm_activate_res");
336 #endif
337
338 context = sm_get_context_data_from_nsapi(prim->nsapi);
339
340 if (context == NULL) {
341 (void)TRACE_ERROR("Non-existing context!");
342 return;
343 }
344
345 /* Forward to User Plane Control */
346 sm_user_plane_control(context, SM_P_SM_ACTIVATE_RES, prim);
347 }
348
349 /*
350 +------------------------------------------------------------------------------
351 | Function : sm_disp_sm_deactivate_res
352 +------------------------------------------------------------------------------
353 | Description : Dispatch SM_DEACTIVATE_RES
354 |
355 | Parameters : prim - received primitive
356 +------------------------------------------------------------------------------
357 */
358 void sm_disp_sm_deactivate_res(T_SM_DEACTIVATE_RES *prim)
359 {
360 int nsapi;
361 struct T_SM_CONTEXT_DATA *context;
362 #ifdef DEBUG_VERBOSE
363 (void)TRACE_FUNCTION("sm_disp_sm_deactivate_res");
364 #endif
365
366 for (nsapi = (int)NAS_NSAPI_5; nsapi < NAS_SIZE_NSAPI; nsapi++) {
367 if (sm_is_nsapi_in_nsapi_set(nsapi, prim->nsapi_set)) {
368 context = sm_get_context_data_from_nsapi(nsapi);
369
370 /* Ignore non-existing contexts */
371 if (context == NULL) {
372 continue;
373 }
374
375 /* Forward to User Plane Control */
376 sm_user_plane_control(context, SM_P_SM_DEACTIVATE_RES, prim);
377
378 /* If SM_DEACTIVATE_RES completed deactivation, free context data */
379 if (sm_is_context_pending_deallocation(context)) {
380 sm_free_context_data_by_nsapi(context->nsapi);
381 }
382 }
383 }
384 }
385
386 /*
387 +------------------------------------------------------------------------------
388 | Function : sm_disp_sm_modify_res
389 +------------------------------------------------------------------------------
390 | Description : Dispatch SM_MODIFY_RES
391 |
392 | Parameters : prim - received primitive
393 +------------------------------------------------------------------------------
394 */
395 void sm_disp_sm_modify_res(T_SM_MODIFY_RES *prim)
396 {
397 struct T_SM_CONTEXT_DATA *context;
398 #ifdef DEBUG_VERBOSE
399 (void)TRACE_FUNCTION("sm_disp_sm_modify_res");
400 #endif
401
402 context = sm_get_context_data_from_nsapi(prim->nsapi);
403
404 if (context == NULL) {
405 (void)TRACE_ERROR("Non-existing context!");
406 return;
407 }
408
409 /* Forward to User Plane Control */
410 sm_user_plane_control(context, SM_P_SM_MODIFY_RES, prim);
411 }
412
413 /*
414 +------------------------------------------------------------------------------
415 | Function : sm_disp_sm_status_req
416 +------------------------------------------------------------------------------
417 | Description : Dispatch SM_STATUS_REQ
418 |
419 | Parameters : prim - received primitive
420 +------------------------------------------------------------------------------
421 */
422 void sm_disp_sm_status_req(T_SM_STATUS_REQ *prim)
423 {
424 #ifdef DEBUG_VERBOSE
425 (void)TRACE_FUNCTION("sm_disp_sm_status_req");
426 #endif
427
428 /* Forward to Sequencer */
429 sm_sequencer(SM_P_SM_STATUS_REQ, prim);
430 }
431
432 /*
433 +------------------------------------------------------------------------------
434 | Function : sm_disp_mmpm_attach_ind
435 +------------------------------------------------------------------------------
436 | Description : Dispatch MMPM_ATTACH_IND
437 |
438 | Parameters : prim - received primitive
439 +------------------------------------------------------------------------------
440 */
441 void sm_disp_mmpm_attach_ind(T_MMPM_ATTACH_IND *prim)
442 {
443 #ifdef DEBUG_VERBOSE
444 (void)TRACE_FUNCTION("sm_disp_mmpm_attach_ind");
445 #endif
446
447 sm_data.sm_attached = TRUE;
448
449 /* Forward to Sequencer */
450 sm_sequencer(SM_P_MMPM_ATTACH_IND, prim);
451 }
452
453 /*
454 +------------------------------------------------------------------------------
455 | Function : sm_disp_mmpm_detach_ind
456 +------------------------------------------------------------------------------
457 | Description : Dispatch MMPM_DETACH_IND
458 |
459 | Parameters : prim - received primitive
460 +------------------------------------------------------------------------------
461 */
462 void sm_disp_mmpm_detach_ind(T_MMPM_DETACH_IND *prim)
463 {
464 #ifdef DEBUG_VERBOSE
465 (void)TRACE_FUNCTION("sm_disp_mmpm_detach_ind");
466 #endif
467
468 sm_data.sm_attached = FALSE;
469
470 /* Forward to Sequencer */
471 sm_sequencer(SM_P_MMPM_DETACH_IND, prim);
472 }
473
474 /*
475 +------------------------------------------------------------------------------
476 | Function : sm_disp_mmpm_suspend_ind
477 +------------------------------------------------------------------------------
478 | Description : Dispatch MMPM_SUSPEND_IND
479 |
480 | Parameters : mm_suspend_ind - received primitive
481 +------------------------------------------------------------------------------
482 */
483 void sm_disp_mmpm_suspend_ind(/*@unused@*/ T_MMPM_SUSPEND_IND *prim)
484 {
485 int nsapi;
486 struct T_SM_CONTEXT_DATA *context;
487 #ifdef DEBUG_VERBOSE
488 (void)TRACE_FUNCTION("sm_disp_mmpm_suspend_ind");
489 #endif
490 sm_data.sm_suspended = TRUE;
491 sm_data.sm_suspend_cause = prim->ps_cause.value.mm_cause;
492
493 for (nsapi = (int)NAS_NSAPI_5; nsapi < NAS_SIZE_NSAPI; nsapi++) {
494 context = sm_get_context_data_from_nsapi(nsapi);
495 if (context != NULL) {
496 sm_network_control(context, SM_P_MMPM_SUSPEND_IND, NULL);
497 }
498 }
499 }
500
501 /*
502 +------------------------------------------------------------------------------
503 | Function : sm_disp_mmpm_resume_ind
504 +------------------------------------------------------------------------------
505 | Description : Dispatch MMPM_RESUME_IND
506 |
507 | Parameters : mm_resume_ind - received primitive
508 +------------------------------------------------------------------------------
509 */
510 void sm_disp_mmpm_resume_ind(/*@unused@*/ T_MMPM_RESUME_IND *prim)
511 {
512 int nsapi;
513 struct T_SM_CONTEXT_DATA *context;
514 #ifdef DEBUG_VERBOSE
515 (void)TRACE_FUNCTION("sm_disp_mmpm_resume_ind");
516 #endif
517
518 sm_data.sm_suspended = FALSE;
519 sm_data.sm_suspend_cause = CAUSE_MM_SUCCESS;
520
521 for (nsapi = (int)NAS_NSAPI_5; nsapi < NAS_SIZE_NSAPI; nsapi++) {
522 context = sm_get_context_data_from_nsapi(nsapi);
523 if (context != NULL) {
524 sm_network_control(context, SM_P_MMPM_RESUME_IND, NULL);
525 }
526 }
527 }
528
529 /*
530 +------------------------------------------------------------------------------
531 | Function : sm_disp_pei_timeout
532 +------------------------------------------------------------------------------
533 | Description : Dispatch pei_timeout
534 |
535 | Parameters : index - system timer index (index into sm_context_array)
536 +------------------------------------------------------------------------------
537 */
538 void sm_disp_pei_timeout(U16 index)
539 {
540 int nsapi;
541 struct T_SM_CONTEXT_DATA *context;
542 #ifdef DEBUG_VERBOSE
543 (void)TRACE_FUNCTION("sm_disp_pei_timeout");
544 #endif
545
546 if (index > (U16)SM_MAX_NSAPI_OFFSET) {
547 (void)TRACE_ERROR("Invalid timer index received!");
548 return;
549 }
550
551 nsapi = sm_index_to_nsapi((U8)index);
552
553 context = sm_get_context_data_from_nsapi(nsapi);
554
555 if (context == NULL) {
556 (void)TRACE_EVENT_P1("Warning! Received timeout on non-existing NSAPI #%d; ignored...", nsapi);
557 return;
558 }
559
560 if ((T_SM_TIMER_TYPE)context->active_timer == SM_TIMER_NONE) {
561 (void)TRACE_EVENT_P1("Warning! Received timeout on NSAPI #%d, which has no active timer; ignored...", nsapi);
562 return;
563 }
564
565 if (context->timeouts == (U8)0) {
566 (void)TRACE_EVENT_P1("Warning! Received timeout on NSAPI #%d, which has no remaining timeouts; ignored...", nsapi);
567 return;
568 }
569
570 /* Decrement remaining timeouts */
571 context->timeouts -= (U8)1;
572
573 /* Check remaining timeouts */
574 if (context->timeouts > (U8)0) {
575 T_SM_NETWORK_CONTROL_EVENT event;
576 /* More timeouts remaining - restart timer */
577 sm_timer_restart(context);
578
579 /* Inform Network Control of the timeout */
580 switch (context->active_timer) {
581 case SM_TIMER_T3380: event = SM_T_T3380; break;
582 case SM_TIMER_T3381: event = SM_T_T3381; break;
583 case SM_TIMER_T3390: event = SM_T_T3390; break;
584 default: return;
585 }
586 sm_network_control(context, event, NULL);
587 } else {
588 T_SM_NETWORK_CONTROL_EVENT event;
589 /* No timeouts remaining - Inform Network Control of the timer expiry */
590 switch (context->active_timer) {
591 case SM_TIMER_T3380: event = SM_T_T3380_MAX; break;
592 case SM_TIMER_T3381: event = SM_T_T3381_MAX; break;
593 case SM_TIMER_T3390: event = SM_T_T3390_MAX; break;
594 default: return;
595 }
596 sm_network_control(context, event, NULL);
597 } /* if */
598
599 /* Deallocate context if it was marked for deactivation due to T3390 max
600 * This change is separately taken from TI DK. Context data is cleaned up
601 * after deactivation due to max T3390 expiry. If this is not done the next
602 * context activation on the same nsapi will fail.
603 */
604 if (sm_is_context_pending_deallocation(context)) {
605 sm_free_context_data_by_nsapi(context->nsapi);
606 }
607 }
608
609 /*==== END OF FILE ==========================================================*/