comparison src/g23m-gprs/llc/llc_up.c @ 1:d393cd9bb723

src/g23m-*: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:40:46 +0000
parents
children
comparison
equal deleted inserted replaced
0:b6a5e36de839 1:d393cd9bb723
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() */