FreeCalypso > hg > fc-tourmaline
comparison src/g23m-gprs/llc/llc_up.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 +----------------------------------------------------------------------------- | |
3 | Project : | |
4 | Modul : | |
5 +----------------------------------------------------------------------------- | |
6 | Copyright 2002 Texas Instruments Berlin, AG | |
7 | All rights reserved. | |
8 | | |
9 | This file is confidential and a trade secret of Texas | |
10 | Instruments Berlin, AG | |
11 | The receipt of or possession of this file does not convey | |
12 | any rights to reproduce or disclose its contents or to | |
13 | manufacture, use, or sell anything it may describe, in | |
14 | whole, or in part, without the specific written consent of | |
15 | Texas Instruments Berlin, AG. | |
16 +----------------------------------------------------------------------------- | |
17 | Purpose : This modul is part of the entity LLC and implements all | |
18 | functions to handles the incoming primitives as described in | |
19 | the SDL-documentation (U-statemachine) | |
20 +----------------------------------------------------------------------------- | |
21 */ | |
22 | |
23 #ifndef LLC_UP_C | |
24 #define LLC_UP_C | |
25 #endif | |
26 | |
27 #define ENTITY_LLC | |
28 | |
29 /*==== INCLUDES =============================================================*/ | |
30 | |
31 #include <string.h> /* to get memcpy() */ | |
32 | |
33 #include "typedefs.h" /* to get Condat data types */ | |
34 #include "vsi.h" /* to get a lot of macros */ | |
35 #include "macdef.h" | |
36 #include "gprs.h" | |
37 #include "gsm.h" /* to get a lot of macros */ | |
38 #include "cnf_llc.h" /* to get cnf-definitions */ | |
39 #include "mon_llc.h" /* to get mon-definitions */ | |
40 #include "prim.h" /* to get the definitions of used SAP and directions */ | |
41 #include "llc.h" /* to get the global entity definitions */ | |
42 | |
43 #include "llc_uf.h" /* to get local U functions */ | |
44 #include "llc_ul.h" /* to get local U labels */ | |
45 #include "llc_t200s.h" /* to get signal interface to T200 */ | |
46 #include "llc_txs.h" /* to get signal interface to TX */ | |
47 #include "llc_llmes.h" /* to get signal interface to LLME */ | |
48 | |
49 /*==== CONST ================================================================*/ | |
50 | |
51 /*==== LOCAL VARS ===========================================================*/ | |
52 | |
53 /*==== PRIVATE FUNCTIONS ====================================================*/ | |
54 | |
55 /*==== PUBLIC FUNCTIONS =====================================================*/ | |
56 | |
57 | |
58 | |
59 /* | |
60 +------------------------------------------------------------------------------ | |
61 | Function : u_ll_establish_req | |
62 +------------------------------------------------------------------------------ | |
63 | Description : Handles the primitive LL_ESTABLISH_REQ | |
64 | | |
65 | Parameters : *ll_establish_req - Ptr to primitive payload | |
66 | | |
67 +------------------------------------------------------------------------------ | |
68 */ | |
69 GLOBAL void u_ll_establish_req ( T_LL_ESTABLISH_REQ *ll_establish_req ) | |
70 { | |
71 int bytelen; | |
72 | |
73 TRACE_FUNCTION( "ll_establish_req" ); | |
74 | |
75 SWITCH_LLC (ll_establish_req->sapi); | |
76 | |
77 TRACE_2_PARA("s:%d xid-len:%d", ll_establish_req->sapi, BYTELEN(ll_establish_req->sdu.l_buf) ); | |
78 | |
79 /* | |
80 * Set TLLI for current transaction. | |
81 */ | |
82 llc_data->u->current_tlli = llc_data->tlli_new; | |
83 | |
84 if (llc_data->u->ll_xid_resp_pending EQ TRUE) | |
85 { | |
86 PFREE (ll_establish_req); | |
87 TRACE_0_INFO( "LL_ESTABLISH_REQ ignored due to LL_XID_IND collision" ); | |
88 return; | |
89 } | |
90 | |
91 switch (GET_STATE(U)) | |
92 { | |
93 case U_ADM: | |
94 /* | |
95 * store Layer-3 XID negotiation parameters, free | |
96 * LL_ESTABLISH_REQ, set retransmission counter to 0 | |
97 * and remember to CNF the establishment afterwards | |
98 */ | |
99 | |
100 /* | |
101 * The layer_3 xid is valid any time, even it is a | |
102 * zero lenght sdu. In this case we have to include | |
103 * an empty l3 xid information field. | |
104 */ | |
105 llc_data->requested_l3_xid->valid = TRUE; | |
106 | |
107 bytelen = BYTELEN( ll_establish_req->sdu.l_buf); | |
108 bytelen = (bytelen < LLC_MAX_L3_XID_LEN ) ? bytelen : LLC_MAX_L3_XID_LEN; | |
109 | |
110 memcpy( llc_data->requested_l3_xid->value, | |
111 &(ll_establish_req->sdu.buf[ll_establish_req->sdu.o_buf >> 3]), | |
112 bytelen ); | |
113 | |
114 llc_data->requested_l3_xid->length = bytelen; | |
115 | |
116 PFREE (ll_establish_req); | |
117 | |
118 llc_data->u->retransmission_counter = 0; | |
119 | |
120 /* | |
121 * Send LL_ESTABLISH_CNF after successful establishment. | |
122 */ | |
123 llc_data->u->ind_cnf_establishment = CNF_ESTABLISHMENT; | |
124 | |
125 SET_STATE (U, U_LOCAL_ESTABLISHMENT); | |
126 | |
127 /* | |
128 * send SABM (w/ Layer 3 XID parameters), start T200 | |
129 */ | |
130 u_send_sabm (); | |
131 break; | |
132 | |
133 case U_LOCAL_ESTABLISHMENT: | |
134 /* | |
135 * XID Negotiation of layer-3 parameters not supported in | |
136 * this case. | |
137 */ | |
138 PFREE (ll_establish_req); | |
139 | |
140 /* | |
141 * Send LL_ESTABLISH_CNF after successful establishment. | |
142 */ | |
143 llc_data->u->ind_cnf_establishment = CNF_ESTABLISHMENT; | |
144 break; | |
145 | |
146 case U_ABM: | |
147 /* | |
148 * store Layer-3 XID negotiation parameters, free | |
149 * LL_ESTABLISH_REQ, set retransmission counter to 0 | |
150 * and remember to CNF the establishment afterwards | |
151 */ | |
152 | |
153 /* | |
154 * The layer_3 xid is valid any time, even it is a | |
155 * zero lenght sdu. In this case we have to include | |
156 * an empty l3 xid information field. | |
157 */ | |
158 llc_data->requested_l3_xid->valid = TRUE; | |
159 | |
160 bytelen = BYTELEN( ll_establish_req->sdu.l_buf); | |
161 bytelen = (bytelen < LLC_MAX_L3_XID_LEN ) ? bytelen : LLC_MAX_L3_XID_LEN; | |
162 | |
163 memcpy( llc_data->requested_l3_xid->value, | |
164 &(ll_establish_req->sdu.buf[ll_establish_req->sdu.o_buf >> 3]), | |
165 bytelen ); | |
166 | |
167 llc_data->requested_l3_xid->length = bytelen; | |
168 | |
169 PFREE (ll_establish_req); | |
170 | |
171 llc_data->u->retransmission_counter = 0; | |
172 | |
173 /* | |
174 * Send LL_ESTABLISH_CNF after successful establishment. | |
175 */ | |
176 llc_data->u->ind_cnf_establishment = CNF_ESTABLISHMENT; | |
177 | |
178 SET_STATE (U, U_LOCAL_ESTABLISHMENT); | |
179 | |
180 sig_u_llme_abmrel_ind(); | |
181 | |
182 u_send_llgmm_status_ind (LLGMM_ERRCS_L3_REEST); | |
183 | |
184 /* | |
185 * send SABM (w/ Layer 3 XID parameters), start T200 | |
186 */ | |
187 u_send_sabm (); | |
188 break; | |
189 | |
190 case U_ESTABLISH_RES_PENDING: | |
191 case U_REMOTE_ESTABLISHMENT: | |
192 PFREE (ll_establish_req); | |
193 TRACE_0_INFO( "LL_ESTABLISH_REQ ignored due to collision" ); | |
194 break; | |
195 | |
196 default: | |
197 PFREE (ll_establish_req); | |
198 TRACE_ERROR( "LL_ESTABLISH_REQ unexpected" ); | |
199 break; | |
200 } | |
201 | |
202 } /* u_ll_establish_req() */ | |
203 | |
204 | |
205 | |
206 /* | |
207 +------------------------------------------------------------------------------ | |
208 | Function : u_ll_establish_res | |
209 +------------------------------------------------------------------------------ | |
210 | Description : Handles the primitive LL_ESTABLISH_RES | |
211 | | |
212 | Parameters : *ll_establish_res - Ptr to primitive payload | |
213 | | |
214 +------------------------------------------------------------------------------ | |
215 */ | |
216 GLOBAL void u_ll_establish_res ( T_LL_ESTABLISH_RES *ll_establish_res ) | |
217 { | |
218 int bytelen; | |
219 | |
220 TRACE_FUNCTION( "ll_establish_res" ); | |
221 | |
222 SWITCH_LLC (ll_establish_res->sapi); | |
223 | |
224 switch (GET_STATE(U)) | |
225 { | |
226 case U_ESTABLISH_RES_PENDING: | |
227 case U_REMOTE_ESTABLISHMENT: | |
228 if (ll_establish_res->xid_valid == TRUE) | |
229 { | |
230 bytelen = BYTELEN( ll_establish_res->sdu.l_buf); | |
231 | |
232 TRACE_2_PARA("s:%d xid-len:%d", ll_establish_res->sapi, bytelen ); | |
233 | |
234 bytelen = (bytelen < LLC_MAX_L3_XID_LEN ) ? bytelen : LLC_MAX_L3_XID_LEN; | |
235 | |
236 memcpy( llc_data->requested_l3_xid->value, | |
237 &(ll_establish_res->sdu.buf[ll_establish_res->sdu.o_buf >> 3]), | |
238 bytelen ); | |
239 | |
240 llc_data->requested_l3_xid->length = bytelen; | |
241 llc_data->requested_l3_xid->valid = TRUE; | |
242 } | |
243 else | |
244 { | |
245 TRACE_1_PARA("s:%d", ll_establish_res->sapi ); | |
246 | |
247 llc_data->requested_l3_xid->valid = FALSE; | |
248 } | |
249 | |
250 PFREE (ll_establish_res); | |
251 | |
252 if (GET_STATE(U) == U_REMOTE_ESTABLISHMENT) | |
253 { | |
254 /* | |
255 * Send UA response with F bit set to 1 and if valid XID | |
256 */ | |
257 u_send_ua (1, TRUE); | |
258 } | |
259 | |
260 SET_STATE (U, U_ABM); | |
261 | |
262 sig_u_t200_stop_req(); | |
263 | |
264 /* | |
265 * <R.LLC.ABMEST_I.A.012> | |
266 * vs. <R.LLC.ABMEST_I.A.015> | |
267 */ | |
268 sig_u_llme_abmest_ind(); | |
269 break; | |
270 | |
271 default: | |
272 TRACE_1_PARA("s:%d", ll_establish_res->sapi ); | |
273 PFREE (ll_establish_res); | |
274 TRACE_ERROR( "LL_ESTABLISH_RES unexpected" ); | |
275 break; | |
276 } | |
277 | |
278 } /* u_ll_establish_res() */ | |
279 | |
280 | |
281 | |
282 /* | |
283 +------------------------------------------------------------------------------ | |
284 | Function : u_ll_release_req | |
285 +------------------------------------------------------------------------------ | |
286 | Description : Handles the primitive LL_RELEASE_REQ | |
287 | | |
288 | Parameters : *ll_release_req - Ptr to primitive payload | |
289 | | |
290 +------------------------------------------------------------------------------ | |
291 */ | |
292 GLOBAL void u_ll_release_req ( T_LL_RELEASE_REQ *ll_release_req ) | |
293 { | |
294 TRACE_FUNCTION( "ll_release_req" ); | |
295 | |
296 SWITCH_LLC (ll_release_req->sapi); | |
297 | |
298 TRACE_1_PARA("s:%d", ll_release_req->sapi ); | |
299 | |
300 /* | |
301 * Set TLLI for current transaction. | |
302 */ | |
303 llc_data->u->current_tlli = llc_data->tlli_new; | |
304 | |
305 switch (GET_STATE(U)) | |
306 { | |
307 case U_TLLI_UNASSIGNED: | |
308 case U_ADM: | |
309 /* | |
310 * We are already released. Send anytime a LL_RELEASE_CNF to | |
311 * SNDCP to make it more stable. | |
312 */ | |
313 { | |
314 PPASS (ll_release_req, ll_release_cnf, LL_RELEASE_CNF); | |
315 TRACE_0_INFO("LL_RELEASE_REQ not necessary"); | |
316 TRACE_1_OUT_PARA("s:%d", ll_release_cnf->sapi); | |
317 PSEND (hCommSNDCP, ll_release_cnf); | |
318 } | |
319 break; | |
320 | |
321 case U_ABM: | |
322 sig_u_llme_abmrel_ind(); | |
323 /* | |
324 * No break. | |
325 */ | |
326 case U_ESTABLISH_RES_PENDING: | |
327 if (ll_release_req->local EQ LL_REL_LOCAL) | |
328 { | |
329 /* | |
330 * Send LL_RELEASE_CNF to SNDCP. | |
331 */ | |
332 PPASS (ll_release_req, ll_release_cnf, LL_RELEASE_CNF); | |
333 TRACE_1_OUT_PARA("s:%d", ll_release_cnf->sapi); | |
334 PSEND (hCommSNDCP, ll_release_cnf); | |
335 | |
336 SET_STATE (U, U_ADM); | |
337 | |
338 sig_u_t200_stop_req(); | |
339 } | |
340 else /* LL_REL_NOTLOCAL */ | |
341 { | |
342 PFREE (ll_release_req); | |
343 | |
344 llc_data->u->retransmission_counter = 0; | |
345 | |
346 SET_STATE (U, U_LOCAL_RELEASE); | |
347 | |
348 /* | |
349 * Send GRLC_DATA_REQ (DISC), start T200. | |
350 */ | |
351 u_send_disc(); | |
352 } | |
353 break; | |
354 | |
355 case U_REMOTE_ESTABLISHMENT: | |
356 /* | |
357 * We are currently waiting for a LL_ESTABLISH_RSP. But | |
358 * because SNDCP want's us to release the connection, we | |
359 * do so and switch back to ADM operation. | |
360 */ | |
361 SET_STATE (U, U_ADM); | |
362 | |
363 if (ll_release_req->local NEQ LL_REL_LOCAL) | |
364 { | |
365 /* | |
366 * Send DM response with F bit set to 1 | |
367 */ | |
368 llc_data->u->retransmission_counter = 0; | |
369 | |
370 u_send_dm (1); | |
371 } | |
372 | |
373 sig_u_t200_stop_req(); | |
374 | |
375 { | |
376 PPASS (ll_release_req, ll_release_cnf, LL_RELEASE_CNF); | |
377 TRACE_1_OUT_PARA("s:%d", ll_release_cnf->sapi); | |
378 PSEND (hCommSNDCP, ll_release_cnf); | |
379 } | |
380 break; | |
381 | |
382 case U_LOCAL_ESTABLISHMENT: | |
383 if (ll_release_req->local EQ LL_REL_LOCAL) | |
384 { | |
385 /* | |
386 * Stop all running procedures. The peer will do the same. | |
387 * Send the LL_RELEASE_CNF to SNDCP. | |
388 */ | |
389 PPASS (ll_release_req, ll_release_cnf, LL_RELEASE_CNF); | |
390 TRACE_1_OUT_PARA("s:%d", ll_release_cnf->sapi); | |
391 PSEND (hCommSNDCP, ll_release_cnf); | |
392 | |
393 SET_STATE (U, U_ADM); | |
394 | |
395 /* | |
396 * NOTE: The peer may have sent an UA or DM before being released | |
397 * locally itselve. If we get an UA in state ADM we have to | |
398 * send an status indication to GMM. This seems to be ok (ANS). | |
399 * If not, we have to wait until T200 timeout, but this is 40s | |
400 * on SAPI 11 per default. A unexpected DM response will be | |
401 * ignored in state ADM and therefore no problem. | |
402 */ | |
403 | |
404 sig_u_t200_stop_req(); | |
405 } | |
406 else /* LL_REL_NOTLOCAL */ | |
407 { | |
408 /* | |
409 * We have just sent an SABM to our peer. The release request has to | |
410 * be stored and handled later: | |
411 * 1. after timeout of T200 don't restart timer and send rel cnf | |
412 * 2. after receive DM send rel cnf | |
413 * 3. after receive of an UA send DISC and after get UA send rel cnf | |
414 */ | |
415 llc_data->u->release_requested = TRUE; | |
416 /* | |
417 * Clear flag after sending an release confirmation or indication. | |
418 */ | |
419 | |
420 PFREE (ll_release_req); | |
421 TRACE_0_INFO("Release request stored"); | |
422 } | |
423 break; | |
424 | |
425 case U_LOCAL_RELEASE: | |
426 /* | |
427 * release will indicated later | |
428 */ | |
429 TRACE_0_INFO("LL_RELEASE_REQ already received"); | |
430 PFREE (ll_release_req); | |
431 break; | |
432 | |
433 default: | |
434 PFREE (ll_release_req); | |
435 TRACE_ERROR( "LL_RELEASE_REQ unexpected" ); | |
436 break; | |
437 } | |
438 | |
439 } /* u_ll_release_req() */ | |
440 | |
441 | |
442 | |
443 /* | |
444 +------------------------------------------------------------------------------ | |
445 | Function : u_ll_xid_req | |
446 +------------------------------------------------------------------------------ | |
447 | Description : Handles the primitive LL_XID_REQ | |
448 | | |
449 | Parameters : *ll_xid_req - Ptr to primitive payload | |
450 | | |
451 +------------------------------------------------------------------------------ | |
452 */ | |
453 GLOBAL void u_ll_xid_req ( T_LL_XID_REQ *ll_xid_req ) | |
454 { | |
455 int bytelen; | |
456 | |
457 TRACE_FUNCTION( "u_ll_xid_req" ); | |
458 | |
459 SWITCH_LLC (ll_xid_req->sapi); | |
460 | |
461 TRACE_2_PARA("s:%d xid-len:%d", ll_xid_req->sapi, BYTELEN(ll_xid_req->sdu.l_buf) ); | |
462 | |
463 if (llc_data->u->ll_xid_resp_pending EQ TRUE) | |
464 { | |
465 PFREE (ll_xid_req); | |
466 TRACE_0_INFO( "LL_XID_REQ ignored due to LL_XID_IND collision" ); | |
467 return; | |
468 } | |
469 | |
470 switch (GET_STATE(U)) | |
471 { | |
472 case U_ABM: | |
473 case U_ADM: | |
474 /* | |
475 * Copy L3-XID parameter to requested_xid | |
476 * and if currently no cmd frame outstanding, | |
477 * send XID command frame | |
478 */ | |
479 bytelen = BYTELEN( ll_xid_req->sdu.l_buf); | |
480 bytelen = (bytelen < LLC_MAX_L3_XID_LEN ) ? bytelen : LLC_MAX_L3_XID_LEN; | |
481 | |
482 memcpy( llc_data->requested_l3_xid->value, | |
483 &(ll_xid_req->sdu.buf[ll_xid_req->sdu.o_buf >> 3]), | |
484 bytelen ); | |
485 | |
486 llc_data->requested_l3_xid->length = bytelen; | |
487 llc_data->requested_l3_xid->valid = TRUE; | |
488 | |
489 PFREE (ll_xid_req); | |
490 | |
491 if (llc_data->sapi->pbit_outstanding == FALSE) | |
492 { | |
493 /* | |
494 * No frame with pbit set to 1 currently | |
495 * outstanding, send XID comand | |
496 */ | |
497 llc_data->u->retransmission_counter = 0; | |
498 u_tag_xid_parameters(MS_COMMAND, FALSE); | |
499 u_send_xid (MS_COMMAND); | |
500 } | |
501 /* SET_STATE (U, SAME_STATE); */ | |
502 break; | |
503 | |
504 case U_ESTABLISH_RES_PENDING: | |
505 case U_REMOTE_ESTABLISHMENT: | |
506 PFREE (ll_xid_req); | |
507 TRACE_0_INFO( "LL_XID_REQ ignored due to collision" ); | |
508 break; | |
509 | |
510 default: | |
511 /* | |
512 * XID only supported in states ADM + ABM | |
513 */ | |
514 PFREE (ll_xid_req); | |
515 TRACE_ERROR( "LL_XID_REQ unexpected" ); | |
516 break; | |
517 } | |
518 | |
519 } /* u_ll_xid_req() */ | |
520 | |
521 | |
522 | |
523 /* | |
524 +------------------------------------------------------------------------------ | |
525 | Function : u_ll_xid_res | |
526 +------------------------------------------------------------------------------ | |
527 | Description : Handles the primitive LL_XID_RES | |
528 | | |
529 | Parameters : *ll_xid_res - Ptr to primitive payload | |
530 | | |
531 +------------------------------------------------------------------------------ | |
532 */ | |
533 GLOBAL void u_ll_xid_res ( T_LL_XID_RES *ll_xid_res ) | |
534 { | |
535 int bytelen; | |
536 | |
537 TRACE_FUNCTION( "ll_xid_res" ); | |
538 | |
539 SWITCH_LLC (ll_xid_res->sapi); | |
540 | |
541 TRACE_2_PARA("s:%d xid-len:%d", ll_xid_res->sapi, BYTELEN(ll_xid_res->sdu.l_buf) ); | |
542 | |
543 llc_data->u->ll_xid_resp_pending = FALSE; | |
544 | |
545 switch (GET_STATE(U)) | |
546 { | |
547 case U_ABM: | |
548 case U_ADM: | |
549 /* | |
550 * Copy L3-XID parameter to requested_xid | |
551 * and send XID response frame | |
552 */ | |
553 bytelen = BYTELEN( ll_xid_res->sdu.l_buf); | |
554 bytelen = (bytelen < LLC_MAX_L3_XID_LEN ) ? bytelen : LLC_MAX_L3_XID_LEN; | |
555 | |
556 memcpy( llc_data->requested_l3_xid->value, | |
557 &(ll_xid_res->sdu.buf[ll_xid_res->sdu.o_buf >> 3]), | |
558 bytelen ); | |
559 | |
560 llc_data->requested_l3_xid->length = bytelen; | |
561 llc_data->requested_l3_xid->valid = TRUE; | |
562 | |
563 PFREE (ll_xid_res); | |
564 | |
565 u_tag_xid_parameters(MS_RESPONSE, FALSE); | |
566 u_send_xid (MS_RESPONSE); | |
567 | |
568 /* SET_STATE (U, SAME_STATE); */ | |
569 break; | |
570 | |
571 default: | |
572 /* | |
573 * XID only supported in states ADM + ABM | |
574 */ | |
575 PFREE (ll_xid_res); | |
576 TRACE_ERROR( "LL_XID_RES unexpected" ); | |
577 break; | |
578 } | |
579 | |
580 } /* u_ll_xid_res() */ |