00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #include <stdlib.h>
00078 #include <stdio.h>
00079 #include <string.h>
00080 #include <stdarg.h>
00081
00082 #include "Q921.h"
00083 #include "Q921priv.h"
00084 #include "mfifo.h"
00085
00086
00087
00088
00089
00090
00091
00096 static struct Q921StateName {
00097 Q921State_t value;
00098 const char *name;
00099 } Q921StateNames[10] = {
00100 { Q921_STATE_STOPPED, "Stopped" },
00101 { Q921_STATE_TEI_UNASSIGNED, "TEI Unassigned" },
00102 { Q921_STATE_TEI_AWAITING, "TEI Awaiting Assignment" },
00103 { Q921_STATE_TEI_ESTABLISH, "TEI Awaiting Establishment" },
00104 { Q921_STATE_TEI_ASSIGNED, "TEI Assigned" },
00105 { Q921_STATE_AWAITING_ESTABLISHMENT, "Awaiting Establishment" },
00106 { Q921_STATE_AWAITING_RELEASE, "Awaiting Release" },
00107 { Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, "Multiple Frame Mode Established" },
00108 { Q921_STATE_TIMER_RECOVERY, "Timer Recovery" },
00109 { 0, 0 }
00110 };
00111
00120 static const char *Q921State2Name(Q921State_t state)
00121 {
00122 struct Q921StateName *p = Q921StateNames;
00123
00124 while(p->name) {
00125 if(p->value == state)
00126 return p->name;
00127 p++;
00128 }
00129
00130 return "Unknown";
00131 }
00132
00133
00137 static int Q921SendEnquiry(L2TRUNK trunk, L2UCHAR tei)
00138 {
00139 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00140
00141
00142 if(Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) {
00143
00144 Q921SendRNR(trunk, trunk->sapi, Q921_COMMAND(trunk), tei, 1);
00145 }
00146 else {
00147 Q921SendRR(trunk, trunk->sapi, Q921_COMMAND(trunk), tei, 1);
00148 }
00149
00150
00151 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
00152
00153
00154 Q921T200TimerReset(trunk, tei);
00155
00156
00157 return 1;
00158 }
00159
00163 static int Q921SendEnquiryResponse(L2TRUNK trunk, L2UCHAR tei)
00164 {
00165 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00166
00167
00168 if(Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) {
00169
00170 Q921SendRNR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 1);
00171 }
00172 else {
00173 Q921SendRR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 1);
00174
00175
00176 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
00177 }
00178
00179 return 1;
00180 }
00181
00189 static void Q921ResetExceptionConditions(L2TRUNK trunk, L2UCHAR tei)
00190 {
00191 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00192
00193
00194 Q921_CLEAR_FLAG(link, Q921_FLAG_PEER_RECV_BUSY);
00195
00196
00197 Q921_CLEAR_FLAG(link, Q921_FLAG_REJECT);
00198
00199
00200 Q921_CLEAR_FLAG(link, Q921_FLAG_RECV_BUSY);
00201
00202
00203 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
00204
00205 return;
00206 }
00207
00215 static int Q921EstablishDataLink(L2TRUNK trunk, L2UCHAR tei)
00216 {
00217 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00218
00219
00220 Q921ResetExceptionConditions(trunk, tei);
00221
00222
00223 link->N200 = 0;
00224
00225
00226 Q921SendSABME(trunk, trunk->sapi, Q921_COMMAND(trunk), tei, 1);
00227
00228
00229 Q921T200TimerReset(trunk, tei);
00230 Q921T203TimerStop(trunk, tei);
00231
00232 return 1;
00233 }
00234
00242 static int Q921NrErrorRecovery(L2TRUNK trunk, L2UCHAR tei)
00243 {
00244 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00245
00246
00247
00248
00249 Q921EstablishDataLink(trunk, tei);
00250
00251
00252 Q921_CLEAR_FLAG(link, Q921_FLAG_L3_INITIATED);
00253
00254 return 1;
00255 }
00256
00257
00266 static int Q921InvokeRetransmission(L2TRUNK trunk, L2UCHAR tei, L2UCHAR nr)
00267 {
00268 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00269 L2UCHAR *mes;
00270 L2INT qpos, qnum, size = 0;
00271
00272 qnum = MFIFOGetMesCount(link->IFrameResendQueue);
00273 qpos = qnum - 1;
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 while(link->vs != nr && qpos > 0) {
00297
00298 Q921_DEC_COUNTER(link->vs);
00299
00300
00301 qpos--;
00302 }
00303
00304
00305
00306
00307 if(link->vs != nr && !qpos) {
00308
00309
00310 }
00311
00312
00313
00314
00315
00316 while(qpos < qnum) {
00317
00318 mes = MFIFOGetMesPtrOffset(link->IFrameResendQueue, &size, qpos);
00319 if(mes) {
00320
00321 MFIFOWriteMes(link->IFrameQueue, mes, size);
00322
00323
00324 }
00325
00326 qpos++;
00327 }
00328
00329 return 1;
00330 }
00331
00332
00333 static int Q921AcknowledgePending(L2TRUNK trunk, L2UCHAR tei)
00334 {
00335 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00336
00337 switch(link->state) {
00338 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
00339 case Q921_STATE_TIMER_RECOVERY:
00340 if(Q921_CHECK_FLAG(link, Q921_FLAG_ACK_PENDING)) {
00341
00342 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
00343
00344
00345 Q921SendRR(trunk, trunk->sapi, Q921_COMMAND(trunk), tei, 0);
00346
00347 return 1;
00348 }
00349 break;
00350
00351 default:
00352 break;
00353 }
00354
00355 return 0;
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 int Q921_InitTrunk(L2TRUNK trunk,
00367 L2UCHAR sapi,
00368 L2UCHAR tei,
00369 Q921NetUser_t NetUser,
00370 Q921NetType_t NetType,
00371 L2INT hsize,
00372 Q921Tx21CB_t cb21,
00373 Q921Tx23CB_t cb23,
00374 void *priv21,
00375 void *priv23)
00376 {
00377 int numlinks = 0;
00378
00379 trunk->sapi = sapi;
00380 trunk->tei = tei;
00381 trunk->NetUser = NetUser;
00382 trunk->NetType = NetType;
00383 trunk->Q921Tx21Proc = cb21;
00384 trunk->Q921Tx23Proc = cb23;
00385 trunk->PrivateData21 = priv21;
00386 trunk->PrivateData23 = priv23;
00387 trunk->Q921HeaderSpace = hsize;
00388
00389 numlinks = Q921_IS_PTMP_NT(trunk) ? Q921_TEI_MAX : 1;
00390
00391 if (trunk->initialized != INITIALIZED_MAGIC) {
00392 MFIFOCreate(trunk->HDLCInQueue, Q921MAXHDLCSPACE, 10);
00393
00394
00395
00396
00397 trunk->context = malloc(numlinks * sizeof(struct Q921_Link));
00398 if(!trunk->context)
00399 return -1;
00400
00401 trunk->initialized = INITIALIZED_MAGIC;
00402 }
00403
00404
00405 trunk->T200Timeout = 1000;
00406 trunk->T203Timeout = 10000;
00407 trunk->T202Timeout = 2000;
00408 trunk->T201Timeout = 200000;
00409 trunk->TM01Timeout = 10000;
00410
00411
00412 trunk->N200Limit = 3;
00413 trunk->N201Limit = 260;
00414 trunk->N202Limit = 3;
00415 trunk->k = 7;
00416
00417
00418 trunk->T202 = 0;
00419 trunk->N202 = 0;
00420
00421
00422 memset(trunk->context, 0, numlinks * sizeof(struct Q921_Link));
00423
00424
00425 memset(trunk->tei_map, 0, Q921_TEI_MAX + 1);
00426
00427 if(Q921_IS_PTMP(trunk)) {
00428
00429
00430
00431
00432
00433 trunk->tei = 0;
00434 }
00435
00436 return 0;
00437 }
00438
00439
00448 static int Q921Tx21Proc(L2TRUNK trunk, L2UCHAR *Msg, L2INT size)
00449 {
00450 Q921LogMesg(trunk, Q921_LOG_DEBUG, 0, Msg, size, "Sending frame");
00451
00452 return trunk->Q921Tx21Proc(trunk->PrivateData21, Msg, size);
00453 }
00454
00455
00464 static int Q921Tx23Proc(L2TRUNK trunk, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *Msg, L2INT size)
00465 {
00466 return trunk->Q921Tx23Proc(trunk->PrivateData23, ind, tei, Msg, size);
00467 }
00468
00469
00480 static int Q921Log(L2TRUNK trunk, Q921LogLevel_t level, const char *fmt, ...)
00481 {
00482 char buf[Q921_LOGBUFSIZE];
00483 L2INT len;
00484 va_list ap;
00485
00486 if(!trunk->Q921LogProc)
00487 return 0;
00488
00489 if(trunk->loglevel < level)
00490 return 0;
00491
00492 va_start(ap, fmt);
00493
00494 len = vsnprintf(buf, sizeof(buf)-1, fmt, ap);
00495 if(len <= 0) {
00496
00497 return -1;
00498 }
00499 if(len >= sizeof(buf))
00500 len = sizeof(buf) - 1;
00501
00502 buf[len] = '\0';
00503
00504 va_end(ap);
00505
00506 return trunk->Q921LogProc(trunk->PrivateDataLog, level, buf, len);
00507 }
00508
00509
00510 static int print_hex(char *buf, int bsize, const unsigned char *in, const int len)
00511 {
00512 static const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
00513 int offset = 0;
00514 int pos = 0;
00515 int nr = 0;
00516
00517 buf[pos++] = '[';
00518 bsize -= 3;
00519
00520 while((bsize - pos) > 0 && offset < len) {
00521 buf[pos++] = hex[(in[offset] & 0xF0) >> 4];
00522 buf[pos++] = hex[(in[offset++] & 0x0F)];
00523
00524 if(++nr == 32 && offset < len && (bsize - pos) > 3) {
00525 nr = 0;
00526 buf[pos++] = ']';
00527 buf[pos++] = '\n';
00528 buf[pos++] = '[';
00529 }
00530 else if(offset < len) {
00531 buf[pos++] = ' ';
00532 }
00533 }
00534
00535 buf[pos++] = ']';
00536 buf[pos++] = '\n';
00537 buf[pos] = '\0';
00538
00539 return pos;
00540 }
00541
00542 #define APPEND_MSG(buf, off, lef, fmt, ...) \
00543 len = snprintf(buf + off, lef, fmt, ##__VA_ARGS__); \
00544 if(len > 0) { \
00545 off += len; \
00546 lef -= len; \
00547 } else { \
00548 goto out; \
00549 }
00550
00564 static int Q921LogMesg(L2TRUNK trunk, Q921LogLevel_t level, L2UCHAR received, L2UCHAR *mes, L2INT size, const char *fmt, ...)
00565 {
00566 char buf[Q921_LOGBUFSIZE];
00567 size_t len, left;
00568 va_list ap;
00569
00570 if(!trunk->Q921LogProc)
00571 return 0;
00572
00573 if(trunk->loglevel < level)
00574 return 0;
00575
00576 if(!mes)
00577 return 0;
00578
00579 memset(buf, 0, sizeof(buf));
00580
00581 left = sizeof(buf) - 1;
00582
00583 va_start(ap, fmt);
00584
00585 len = vsnprintf(buf, left, fmt, ap);
00586 if(len > 0)
00587 left -= len;
00588 else {
00589
00590 return -1;
00591 }
00592
00593 va_end(ap);
00594
00595 if(trunk->loglevel == Q921_LOG_DEBUG) {
00596 char pbuf[1024];
00597 size_t pleft, poffset;
00598 L2UCHAR sapi, tei, cr;
00599 L2UCHAR *pmes = mes + trunk->Q921HeaderSpace;
00600 struct Q921_Link *link;
00601
00602 memset(pbuf, 0, sizeof(pbuf));
00603
00604 pleft = sizeof(pbuf);
00605 poffset = 0;
00606
00607
00608
00609
00610 sapi = (pmes[0] & 0xfc) >> 2;
00611 cr = (pmes[0] & 0x02) >> 1;
00612 tei = (pmes[1] & 0xfe) >> 1;
00613 link = Q921_LINK_CONTEXT(trunk, tei);
00614
00615
00616 cr = (received) ? Q921_IS_COMMAND(trunk, cr) : Q921_IS_RESPONSE(trunk, cr);
00617
00618
00619 if((pmes[2] & 0x01) == 0x00) {
00620 ;
00621 }
00622 else if((pmes[2] & 0x03) == 0x01) {
00623 ;
00624 }
00625 else if((pmes[2] & 0x03) == 0x03) {
00626 ;
00627 }
00628
00629 APPEND_MSG(pbuf, poffset, pleft, "\n----------------- Q.921 Packet [%s%s] ---------------\n", received ? "Incoming" : "Outgoing",
00630 (tei == link->tei || tei == Q921_TEI_BCAST) ? "" : ", Ignored" );
00631
00632
00633 APPEND_MSG(pbuf, poffset, pleft, " SAPI: %u, TEI: %u, C/R: %s (%d)\n\n", sapi, tei, (cr) ? "Command" : "Response", (mes[0] & 0x02) >> 1 );
00634
00635
00636
00637
00638 if((pmes[2] & 0x01) == 0x00) {
00639
00640
00641
00642 L2UCHAR pf = pmes[3] & 0x01;
00643 L2UCHAR nr = pmes[3] >> 1;
00644 L2UCHAR ns = pmes[2] >> 1;
00645
00646 APPEND_MSG(pbuf, poffset, pleft, " Type: I Frame\n P/F: %d, N(S): %d, N(R): %d [V(A): %d, V(R): %d, V(S): %d]\n", pf, ns, nr,
00647 link->va, link->vr, link->vs);
00648
00649
00650 if(tei != link->tei) {
00651 APPEND_MSG(pbuf, poffset, pleft, " CONTENT:\n");
00652
00653 len = print_hex(pbuf + poffset, pleft, &pmes[4], size - (trunk->Q921HeaderSpace + 4));
00654 poffset += len;
00655 pleft -= len;
00656 }
00657 }
00658 else if((pmes[2] & 0x03) == 0x01) {
00659
00660
00661
00662 L2UCHAR sv = (pmes[2] & 0x0c) >> 2;
00663 L2UCHAR pf = pmes[3] & 0x01;
00664 L2UCHAR nr = pmes[3] >> 1;
00665 const char *type;
00666
00667 switch(sv) {
00668 case 0x00:
00669 type = "RR (Receive Ready)";
00670 break;
00671
00672 case 0x02:
00673 type = "RNR (Receiver Not Ready)";
00674 break;
00675
00676 case 0x04:
00677 type = "REJ (Reject)";
00678 break;
00679
00680 default:
00681 type = "Unknown";
00682 break;
00683 }
00684
00685 APPEND_MSG(pbuf, poffset, pleft, " Type: S Frame, SV: %s\n P/F: %d, N(R): %d [V(A): %d, V(R): %d, V(S): %d]\n", type, pf, nr,
00686 link->va, link->vr, link->vs);
00687 }
00688 else if((pmes[2] & 0x03) == 0x03) {
00689
00690
00691
00692 L2UCHAR m = (pmes[2] & 0xe0) >> 3 | (pmes[2] & 0x0c) >> 2;
00693 L2UCHAR pf = (pmes[2] & 0x10) >> 4;
00694 const char *type;
00695
00696 switch(m) {
00697 case 0x00:
00698 type = "UI (Unnumbered Information)";
00699 break;
00700
00701 case 0x03:
00702 type = "DM (Disconnected Mode)";
00703 break;
00704
00705 case 0x08:
00706 type = "DISC (Disconnect)";
00707 break;
00708
00709 case 0x0c:
00710 type = "UA (Unnumbered Acknowledgement)";
00711 break;
00712
00713 case 0x0f:
00714 type = "SABME";
00715 break;
00716
00717 case 0x11:
00718 type = "FRMR (Frame Reject)";
00719 break;
00720
00721 case 0x17:
00722 type = "XID (Exchange Identification)";
00723 break;
00724
00725 default:
00726 type = "Unknown";
00727 }
00728
00729
00730 APPEND_MSG(pbuf, poffset, pleft, " Type: U Frame (%s)\n P/F: %d\n", type, pf);
00731
00732 if(m == 0x00) {
00733 switch(pmes[3]) {
00734 case Q921_LAYER_ENT_ID_TEI:
00735 type = "TEI Mgmt";
00736 break;
00737
00738 case Q921_LAYER_ENT_ID_Q931:
00739 type = "Q.931";
00740 break;
00741
00742 default:
00743 type = "Unknown";
00744 }
00745
00746 if(pmes[3] == Q921_LAYER_ENT_ID_TEI) {
00747 const char *command = "";
00748
00749 switch(pmes[6]) {
00750 case Q921_TEI_ID_REQUEST:
00751 command = "Request";
00752 break;
00753 case Q921_TEI_ID_VERIFY:
00754 command = "Verify";
00755 break;
00756 case Q921_TEI_ID_CHECKREQ:
00757 command = "Check req";
00758 break;
00759 case Q921_TEI_ID_CHECKRESP:
00760 command = "Check resp";
00761 break;
00762 case Q921_TEI_ID_REMOVE:
00763 command = "Remove";
00764 break;
00765 case Q921_TEI_ID_ASSIGNED:
00766 command = "Assign";
00767 break;
00768 case Q921_TEI_ID_DENIED:
00769 command = "Denied";
00770 break;
00771 }
00772 APPEND_MSG(pbuf, poffset, pleft, " ENT ID: %d (%s), COMMAND: %d (%s), RI: %#x, AI: %d\n",
00773 pmes[3], type, pmes[6], command, (int)((pmes[4] << 8) | pmes[5]), pmes[7] >> 1);
00774 }
00775 else {
00776 APPEND_MSG(pbuf, poffset, pleft, " ENT ID: %d (%s), MESSAGE CONTENT:\n", pmes[3], type);
00777
00778 len = print_hex(pbuf + poffset, pleft, &pmes[3], size - (trunk->Q921HeaderSpace + 3));
00779 poffset += len;
00780 pleft -= len;
00781 }
00782 }
00783 }
00784 else {
00785
00786
00787
00788 strncat(pbuf + poffset, " -- unknown frame type --\n", pleft);
00789
00790 len = (sizeof(pbuf) - poffset) - strlen(pbuf + poffset);
00791 if(len > 0) {
00792 poffset += len;
00793 pleft -= len;
00794 } else
00795 goto out;
00796 }
00797
00798 APPEND_MSG(pbuf, poffset, pleft, "\n Q.921 state: \"%s\" (%d) [flags: %c%c%c%c]\n", Q921State2Name(link->state), link->state,
00799 Q921_CHECK_FLAG(link, Q921_FLAG_ACK_PENDING) ? 'A' : '-',
00800 Q921_CHECK_FLAG(link, Q921_FLAG_REJECT) ? 'R' : '-',
00801 Q921_CHECK_FLAG(link, Q921_FLAG_PEER_RECV_BUSY) ? 'P' : '-',
00802 Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY) ? 'B' : '-');
00803
00804 strncat(pbuf + poffset, "----------------------------------------------\n\n", pleft);
00805
00806 len = (sizeof(pbuf) - poffset) - strlen(pbuf + poffset);
00807 if(len > 0) {
00808 poffset += len;
00809 pleft -= len;
00810 } else
00811 goto out;
00812
00813
00814
00815 len = strlen(pbuf);
00816 if(len <= left)
00817 strncat(buf, pbuf, left);
00818 else
00819 strncat(buf, "-- packet truncated --\n", left);
00820 }
00821
00822 out:
00823 buf[sizeof(buf) - 1] = '\0';
00824
00825 return trunk->Q921LogProc(trunk->PrivateDataLog, level, buf, strlen(buf));
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838 static L2ULONG (*Q921GetTimeProc) (void) = NULL;
00839 static L2ULONG tLast = {0};
00840
00841 static L2ULONG Q921GetTime(void)
00842 {
00843 L2ULONG tNow = 0;
00844
00845 if(Q921GetTimeProc)
00846 {
00847 tNow = Q921GetTimeProc();
00848 if(tNow < tLast)
00849 {
00850
00851 }
00852 tLast = tNow;
00853 }
00854 return tNow;
00855 }
00856
00857
00858
00859
00860 static void Q921T200TimerStart(L2TRUNK trunk, L2UCHAR tei)
00861 {
00862 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00863
00864 if (!link->T200) {
00865 link->T200 = Q921GetTime() + trunk->T200Timeout;
00866
00867 Q921Log(trunk, Q921_LOG_DEBUG, "T200 (timeout: %d msecs) started for TEI %d\n", trunk->T200Timeout, tei);
00868 }
00869 }
00870
00871 static void Q921T200TimerStop(L2TRUNK trunk, L2UCHAR tei)
00872 {
00873 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00874
00875 link->T200 = 0;
00876
00877 Q921Log(trunk, Q921_LOG_DEBUG, "T200 stopped for TEI %d\n", tei);
00878 }
00879
00880 static void Q921T200TimerReset(L2TRUNK trunk, L2UCHAR tei)
00881 {
00882 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00883
00884 link->T200 = Q921GetTime() + trunk->T200Timeout;
00885
00886 Q921Log(trunk, Q921_LOG_DEBUG, "T200 (timeout: %d msecs) restarted for TEI %d\n", trunk->T200Timeout, tei);
00887 }
00888
00889
00890
00891
00892 static void Q921T203TimerStart(L2TRUNK trunk, L2UCHAR tei)
00893 {
00894 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00895
00896 if (!link->T203) {
00897 link->T203 = Q921GetTime() + trunk->T203Timeout;
00898
00899 Q921Log(trunk, Q921_LOG_DEBUG, "T203 (timeout: %d msecs) started for TEI %d\n", trunk->T203Timeout, tei);
00900 }
00901 }
00902
00903 static void Q921T203TimerStop(L2TRUNK trunk, L2UCHAR tei)
00904 {
00905 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00906
00907 link->T203 = 0;
00908
00909 Q921Log(trunk, Q921_LOG_DEBUG, "T203 stopped for TEI %d\n", tei);
00910 }
00911
00912 static void Q921T203TimerReset(L2TRUNK trunk, L2UCHAR tei)
00913 {
00914 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00915
00916 link->T203 = Q921GetTime() + trunk->T203Timeout;
00917
00918 Q921Log(trunk, Q921_LOG_DEBUG, "T203 (timeout: %d msecs) restarted for TEI %d\n", trunk->T203Timeout, tei);
00919 }
00920
00921
00922
00923
00924 static void Q921T202TimerStart(L2TRUNK trunk)
00925 {
00926 if (!trunk->T202) {
00927 trunk->T202 = Q921GetTime() + trunk->T202Timeout;
00928
00929 Q921Log(trunk, Q921_LOG_DEBUG, "T202 (timeout: %d msecs) started\n", trunk->T202Timeout);
00930 }
00931 }
00932
00933 static void Q921T202TimerStop(L2TRUNK trunk)
00934 {
00935 trunk->T202 = 0;
00936
00937 Q921Log(trunk, Q921_LOG_DEBUG, "T202 stopped\n");
00938 }
00939
00940 static void Q921T202TimerReset(L2TRUNK trunk)
00941 {
00942 trunk->T202 = Q921GetTime() + trunk->T202Timeout;
00943
00944 Q921Log(trunk, Q921_LOG_DEBUG, "T202 (timeout: %d msecs) restarted\n", trunk->T202Timeout);
00945 }
00946
00947
00948
00949
00950 static void Q921T201TimerStart(L2TRUNK trunk, L2UCHAR tei)
00951 {
00952 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00953
00954 if (!link->T201) {
00955 link->T201 = Q921GetTime() + trunk->T201Timeout;
00956
00957 Q921Log(trunk, Q921_LOG_DEBUG, "T201 (timeout: %d msecs) started for TEI %d\n", trunk->T201Timeout, tei);
00958 }
00959 }
00960
00961 static void Q921T201TimerStop(L2TRUNK trunk, L2UCHAR tei)
00962 {
00963 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00964
00965 link->T201 = 0;
00966
00967 Q921Log(trunk, Q921_LOG_DEBUG, "T201 stopped for TEI %d\n", tei);
00968 }
00969
00970 #ifdef __UNUSED_FOR_NOW__
00971 static void Q921T201TimerReset(L2TRUNK trunk, L2UCHAR tei)
00972 {
00973 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00974
00975 link->T201 = Q921GetTime() + trunk->T201Timeout;
00976
00977 Q921Log(trunk, Q921_LOG_DEBUG, "T201 (timeout: %d msecs) restarted for TEI %d\n", trunk->T201Timeout, tei);
00978 }
00979 #endif
00980
00981
00982
00983
00984 static void Q921TM01TimerStart(L2TRUNK trunk, L2UCHAR tei)
00985 {
00986 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00987
00988 if (!link->TM01) {
00989 link->TM01 = Q921GetTime() + trunk->TM01Timeout;
00990
00991 Q921Log(trunk, Q921_LOG_DEBUG, "TM01 (timeout: %d msecs) started for TEI %d\n", trunk->TM01Timeout, tei);
00992 }
00993 }
00994
00995 #ifdef __UNUSED_FOR_NOW__
00996 static void Q921TM01TimerStop(L2TRUNK trunk, L2UCHAR tei)
00997 {
00998 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
00999
01000 link->TM01 = 0;
01001
01002 Q921Log(trunk, Q921_LOG_DEBUG, "TM01 stopped for TEI %d\n", tei);
01003 }
01004 #endif
01005
01006 static void Q921TM01TimerReset(L2TRUNK trunk, L2UCHAR tei)
01007 {
01008 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
01009
01010 link->TM01 = Q921GetTime() + trunk->TM01Timeout;
01011
01012 Q921Log(trunk, Q921_LOG_DEBUG, "TM01 (timeout: %d msecs) restarted for TEI %d\n", trunk->TM01Timeout, tei);
01013 }
01014
01015
01016
01017
01018 static void Q921T200TimerExpire(L2TRUNK trunk, L2UCHAR tei)
01019 {
01020 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
01021 struct Q921_Link *trlink = Q921_TRUNK_CONTEXT(trunk);
01022
01023 Q921Log(trunk, Q921_LOG_DEBUG, "T200 expired for TEI %d (trunk TEI %d)\n", tei, trlink->tei);
01024
01025
01026 Q921T200TimerStop(trunk, tei);
01027
01028 switch(link->state) {
01029 case Q921_STATE_AWAITING_ESTABLISHMENT:
01030 if(link->N200 >= trunk->N200Limit) {
01031
01032 MFIFOClear(link->IFrameQueue);
01033
01034
01035 Q921Log(trunk, Q921_LOG_ERROR, "Failed to establish Q.921 link in %d retries\n", link->N200);
01036
01037
01038 Q921Tx23Proc(trunk, Q921_DL_RELEASE, tei, NULL, 0);
01039
01040
01041 Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, tei);
01042
01043 #ifdef Q921_STATISTICS
01044
01045 Q921StatsIncrementCounter(link, Q921_STATS_N200);
01046 #endif
01047 } else {
01048
01049 link->N200++;
01050
01051
01052 Q921SendSABME(trunk,
01053 trunk->sapi,
01054 Q921_COMMAND(trunk),
01055 tei,
01056 1);
01057
01058
01059 Q921T200TimerStart(trunk, tei);
01060 }
01061 break;
01062
01063 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
01064 link->N200 = 0;
01065
01066 if(!Q921_CHECK_FLAG(link, Q921_FLAG_PEER_RECV_BUSY)) {
01067
01068
01069
01070 Q921_DEC_COUNTER(link->vs);
01071
01072
01073
01074
01075
01076
01077
01078 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
01079
01080
01081 Q921T200TimerStart(trunk, tei);
01082 } else {
01083
01084 Q921SendEnquiry(trunk, tei);
01085 }
01086
01087
01088 link->N200++;
01089
01090
01091 Q921ChangeState(trunk, Q921_STATE_TIMER_RECOVERY, tei);
01092 break;
01093
01094 case Q921_STATE_TIMER_RECOVERY:
01095 if(link->N200 == trunk->N200Limit) {
01096
01097
01098
01099 Q921EstablishDataLink(trunk, tei);
01100
01101
01102 Q921_CLEAR_FLAG(link, Q921_FLAG_L3_INITIATED);
01103
01104
01105 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
01106
01107 #ifdef Q921_STATISTICS
01108
01109 Q921StatsIncrementCounter(link, Q921_STATS_N200);
01110 #endif
01111 } else {
01112 if(link->vs == link->va) {
01113
01114 Q921SendEnquiry(trunk, tei);
01115
01116 } else if(!Q921_CHECK_FLAG(link, Q921_FLAG_PEER_RECV_BUSY)) {
01117
01118
01119
01120 Q921_DEC_COUNTER(link->vs);
01121
01122
01123
01124
01125
01126
01127
01128 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
01129
01130
01131 Q921T200TimerStart(trunk, tei);
01132 }
01133
01134
01135 link->N200++;
01136
01137
01138 }
01139 break;
01140
01141 default:
01142 break;
01143 }
01144
01145 #ifdef Q921_STATISTICS
01146
01147 Q921StatsIncrementCounter(link, Q921_STATS_T200);
01148 #endif
01149 }
01150
01151 static void Q921T203TimerExpire(L2TRUNK trunk, L2UCHAR tei)
01152 {
01153 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
01154 struct Q921_Link *trlink = Q921_TRUNK_CONTEXT(trunk);
01155
01156 Q921Log(trunk, Q921_LOG_DEBUG, "T203 expired for TEI %d (trunk TEI %d)\n", tei, trlink->tei);
01157
01158
01159 Q921T203TimerStop(trunk, tei);
01160
01161 switch(link->state) {
01162 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
01163
01164 Q921SendEnquiry(trunk, tei);
01165
01166
01167 link->N200 = 0;
01168
01169
01170 break;
01171
01172 default:
01173 break;
01174 }
01175
01176 #ifdef Q921_STATISTICS
01177
01178 Q921StatsIncrementCounter(link, Q921_STATS_T203);
01179 #endif
01180 }
01181
01182 static void Q921T202TimerExpire(L2TRUNK trunk)
01183 {
01184 struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk);
01185
01186 Q921T202TimerReset(trunk);
01187
01188 Q921Log(trunk, Q921_LOG_DEBUG, "T202 expired for Q.921 trunk with TEI %d\n", link->tei);
01189
01190
01191
01192 switch(link->state) {
01193 case Q921_STATE_TEI_ASSIGNED:
01194 Q921TeiSendVerifyRequest(trunk);
01195 break;
01196
01197 default:
01198
01199 if(trunk->N202 >= trunk->N202Limit) {
01200
01201 trunk->N202 = 0;
01202
01203 Q921T202TimerStop(trunk);
01204
01205 #ifdef Q921_STATISTICS
01206
01207 Q921StatsIncrementCounter(link, Q921_STATS_N202);
01208 #endif
01209 return;
01210 }
01211 Q921TeiSendAssignRequest(trunk);
01212
01213 trunk->N202++;
01214 }
01215
01216 #ifdef Q921_STATISTICS
01217
01218 Q921StatsIncrementCounter(link, Q921_STATS_T202);
01219 #endif
01220 }
01221
01222 static void Q921T201TimerExpire(L2TRUNK trunk, L2UCHAR tei)
01223 {
01224 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
01225 struct Q921_Link *trlink = Q921_TRUNK_CONTEXT(trunk);
01226
01227 Q921Log(trunk, Q921_LOG_DEBUG, "T201 expired for TEI %d (trunk TEI: %d)\n", tei, trlink->tei);
01228
01229 Q921T201TimerStop(trunk, tei);
01230
01231
01232 if(link->N202 < trunk->N202Limit) {
01233
01234 Q921TeiSendCheckRequest(trunk, tei);
01235
01236
01237 link->N202++;
01238 } else {
01239
01240 Q921ChangeState(trunk, Q921_STATE_STOPPED, tei);
01241
01242
01243 memset(link, 0, sizeof(struct Q921_Link));
01244
01245
01246 trunk->tei_map[tei] = 0;
01247
01248 #ifdef Q921_STATISTICS
01249
01250 Q921StatsIncrementCounter(link, Q921_STATS_N202);
01251 #endif
01252 }
01253 #ifdef Q921_STATISTICS
01254
01255 Q921StatsIncrementCounter(trlink, Q921_STATS_T201);
01256 #endif
01257 }
01258
01259 #ifdef __UNUSED_FOR_NOW__
01260 static void Q921TM01TimerExpire(L2TRUNK trunk, L2UCHAR tei)
01261 {
01262 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
01263 struct Q921_Link *trlink = Q921_TRUNK_CONTEXT(trunk);
01264
01265 Q921Log(trunk, Q921_LOG_DEBUG, "TM01 expired for TEI %d (trunk TEI: %d)\n", tei, trlink->tei);
01266
01267
01268 Q921TM01TimerReset(trunk, tei);
01269
01270 switch(link->state) {
01271 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
01272 case Q921_STATE_TIMER_RECOVERY:
01273
01274
01275
01276 #if 0
01277
01278 Q921SendDISC(trunk, trunk->sapi, Q921_COMMAND(trunk), tei, 1);
01279
01280
01281 MFIFOClear(link->IFrameQueue);
01282
01283
01284 Q921ChangeState(trunk, Q921_STATE_AWAITING_RELEASE, tei);
01285 #endif
01286 break;
01287
01288 default:
01289 break;
01290 }
01291
01292 #ifdef Q921_STATISTICS
01293
01294 Q921StatsIncrementCounter(link, Q921_STATS_TM01);
01295 #endif
01296 }
01297 #endif
01298
01299
01300
01301
01302 void Q921TimerTick(L2TRUNK trunk)
01303 {
01304 struct Q921_Link *link;
01305 L2ULONG tNow = Q921GetTime();
01306 int numlinks = Q921_IS_PTMP_NT(trunk) ? Q921_TEI_MAX : 1;
01307 int x;
01308
01309 for(x = 0; x <= numlinks; x++) {
01310 link = Q921_LINK_CONTEXT(trunk, x);
01311
01312
01313 if(link->state == Q921_STATE_STOPPED)
01314 continue;
01315
01316 if (link->T200 && tNow > link->T200) {
01317 Q921T200TimerExpire(trunk, link->tei);
01318 }
01319 if (link->T203 && tNow > link->T203) {
01320 Q921T203TimerExpire(trunk, link->tei);
01321 }
01322
01323 if(Q921_IS_PTMP_NT(trunk) && link->tei) {
01324 if (link->T201 && tNow > link->T201) {
01325 Q921T201TimerExpire(trunk, link->tei);
01326 }
01327 }
01328
01329 if(!Q921_IS_PTMP_NT(trunk)) {
01330 if (trunk->T202 && tNow > trunk->T202) {
01331 Q921T202TimerExpire(trunk);
01332 }
01333 }
01334
01335
01336 Q921SendQueuedIFrame(trunk, link->tei);
01337
01338
01339 Q921AcknowledgePending(trunk, link->tei);
01340 }
01341
01342 }
01343
01344 void Q921SetGetTimeCB(L2ULONG (*callback)(void))
01345 {
01346 Q921GetTimeProc = callback;
01347 }
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368 int Q921QueueHDLCFrame(L2TRUNK trunk, L2UCHAR *b, L2INT size)
01369 {
01370 return MFIFOWriteMes(trunk->HDLCInQueue, b, size);
01371 }
01372
01378 static int Q921EnqueueI(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR *mes, L2INT size)
01379 {
01380 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, Tei);
01381
01382
01383 mes[trunk->Q921HeaderSpace+0] = ((Sapi << 2) & 0xfc) | ((cr << 1) & 0x02);
01384 mes[trunk->Q921HeaderSpace+1] = (Tei << 1) | 0x01;
01385 mes[trunk->Q921HeaderSpace+2] = 0x00;
01386 mes[trunk->Q921HeaderSpace+3] = (pf & 0x01);
01387
01388 Q921Log(trunk, Q921_LOG_DEBUG, "Enqueueing I frame for TEI %d [%d]\n", link->tei, Tei);
01389
01390
01391 MFIFOWriteMes(link->IFrameQueue, mes, size);
01392
01393
01394 Q921SendQueuedIFrame(trunk, link->tei);
01395
01396 return 1;
01397 }
01398
01403 static int Q921SendQueuedIFrame(L2TRUNK trunk, L2UCHAR tei)
01404 {
01405 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
01406
01407 L2INT size = 0;
01408 L2UCHAR *mes;
01409
01410 if(MFIFOGetMesCount(link->IFrameQueue) == 0) {
01411 return 0;
01412 }
01413
01414
01415 if(link->state != Q921_STATE_MULTIPLE_FRAME_ESTABLISHED) {
01416 return 0;
01417 }
01418
01419
01420 if(Q921_CHECK_FLAG(link, Q921_FLAG_PEER_RECV_BUSY)) {
01421 return 0;
01422 }
01423
01424
01425 if(link->vs == ((link->va + trunk->k) % 128)) {
01426 Q921Log(trunk, Q921_LOG_WARNING, "Maximum number (%d) of outstanding I frames reached for TEI %d\n", trunk->k, tei);
01427 return 0;
01428 }
01429
01430 mes = MFIFOGetMesPtr(link->IFrameQueue, &size);
01431 if(mes) {
01432
01433 mes[trunk->Q921HeaderSpace+2] = link->vs << 1;
01434 mes[trunk->Q921HeaderSpace+3] |= link->vr << 1;
01435
01436 if(MFIFOGetMesCount(link->IFrameQueue) == 0) {
01437
01438 }
01439
01440 #ifdef Q921_STATISTICS_VERBOSE
01441 Q921StatsIncrementCounter(link, Q921_STATS_SEND_I);
01442 #endif
01443
01444 Q921Tx21Proc(trunk, mes, size);
01445
01446
01447 Q921_INC_COUNTER(link->vs);
01448
01449
01450 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
01451
01452
01453 if(!link->T200) {
01454
01455 Q921T200TimerStart(trunk, tei);
01456 Q921T203TimerStop(trunk, tei);
01457 }
01458
01459
01460 MFIFOWriteMesOverwrite(link->IFrameResendQueue, mes, size);
01461
01462
01463 MFIFOKillNext(link->IFrameQueue);
01464
01465
01466 if(Q921_IS_NT(trunk)) {
01467 Q921TM01TimerReset(trunk, tei);
01468 }
01469
01470
01471 return 1;
01472 }
01473
01474 return 0;
01475 }
01476
01481 static int Q921SendS(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR sv, L2UCHAR *mes, L2INT size)
01482 {
01483 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, Tei);
01484
01485 if(!Q921_IS_READY(link)) {
01486
01487 Q921Log(trunk, Q921_LOG_DEBUG, "Link not ready, discarding S frame for TEI %d\n", Tei);
01488 return 0;
01489 }
01490
01491
01492 mes[trunk->Q921HeaderSpace+0] = ((Sapi << 2) & 0xfc) | ((cr << 1) & 0x02);
01493 mes[trunk->Q921HeaderSpace+1] = (Tei << 1) | 0x01;
01494 mes[trunk->Q921HeaderSpace+2] = ((sv << 2) & 0x0c) | 0x01;
01495 mes[trunk->Q921HeaderSpace+3] = (link->vr << 1) | (pf & 0x01);
01496
01497 #ifdef Q921_STATISTICS_VERBOSE
01498 Q921StatsIncrementCounter(link, Q921_STATS_SEND_S);
01499 #endif
01500 return Q921Tx21Proc(trunk, mes, size);
01501 }
01502
01503
01508 static int Q921SendU(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR m, L2UCHAR *mes, L2INT size)
01509 {
01510 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, Tei);
01511
01512
01513 mes[trunk->Q921HeaderSpace+0] = ((Sapi << 2) & 0xfc) | ((cr << 1) & 0x02);
01514 mes[trunk->Q921HeaderSpace+1] = (Tei << 1) | 0x01;
01515 mes[trunk->Q921HeaderSpace+2] = ((m << 3) & 0xe0) | ((pf << 4) & 0x10) | ((m << 2) & 0x0c) | 0x03;
01516
01517
01518 if(m == 0x00 && Sapi != Q921_SAPI_TEI && link->state < Q921_STATE_TEI_ASSIGNED) {
01519
01520
01521 MFIFOWriteMes(link->UIFrameQueue, mes, size);
01522
01523 Q921Log(trunk, Q921_LOG_DEBUG, "Link not ready, UI Frame of size %d bytes queued for TEI %d\n", size, Tei);
01524 return 1;
01525 }
01526
01527 #ifdef Q921_STATISTICS_VERBOSE
01528 Q921StatsIncrementCounter(link, Q921_STATS_SEND_U);
01529 #endif
01530 return Q921Tx21Proc(trunk, mes, size);
01531 }
01532
01536 int Q921Rx32(L2TRUNK trunk, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR * Mes, L2INT Size)
01537 {
01538 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
01539 L2INT res = 0;
01540
01541 Q921Log(trunk, Q921_LOG_DEBUG, "Got frame from Q.931, type: %d, tei: %d, size: %d\n", ind, tei, Size);
01542
01543 switch(ind) {
01544 case Q921_DL_ESTABLISH:
01545
01546
01547
01548 switch(link->state) {
01549 case Q921_STATE_TEI_ASSIGNED:
01550 if(!Q921_IS_NT(trunk)) {
01551
01552 Q921EstablishDataLink(trunk, link->tei);
01553
01554
01555 Q921_SET_FLAG(link, Q921_FLAG_L3_INITIATED);
01556
01557
01558 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, link->tei);
01559 }
01560 break;
01561
01562 case Q921_STATE_AWAITING_ESTABLISHMENT:
01563 if(!Q921_IS_NT(trunk)) {
01564
01565 MFIFOClear(link->IFrameQueue);
01566
01567
01568 Q921_SET_FLAG(link, Q921_FLAG_L3_INITIATED);
01569 }
01570 break;
01571
01572 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
01573 case Q921_STATE_TIMER_RECOVERY:
01574 if(!Q921_IS_NT(trunk)) {
01575
01576 MFIFOClear(link->IFrameQueue);
01577
01578
01579 Q921EstablishDataLink(trunk, link->tei);
01580
01581
01582 Q921_SET_FLAG(link, Q921_FLAG_L3_INITIATED);
01583
01584
01585 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, link->tei);
01586 }
01587 break;
01588
01589 default:
01590 break;
01591 }
01592 break;
01593
01594 case Q921_DL_RELEASE:
01595 switch(link->state) {
01596 case Q921_STATE_TEI_ASSIGNED:
01597
01598 Q921Tx23Proc(trunk, Q921_DL_RELEASE, tei, NULL, 0);
01599 break;
01600
01601 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
01602 case Q921_STATE_TIMER_RECOVERY:
01603 if(!Q921_IS_NT(trunk)) {
01604
01605 MFIFOClear(link->IFrameQueue);
01606
01607
01608 link->N200 = 0;
01609
01610
01611 Q921SendDISC(trunk, trunk->sapi, Q921_COMMAND(trunk), link->tei, 1);
01612
01613
01614 if(link->state == Q921_STATE_MULTIPLE_FRAME_ESTABLISHED) {
01615 Q921T203TimerStop(trunk, link->tei);
01616 }
01617 Q921T200TimerReset(trunk, link->tei);
01618
01619
01620 Q921ChangeState(trunk, Q921_STATE_AWAITING_RELEASE, link->tei);
01621 }
01622 break;
01623
01624 default:
01625 break;
01626 }
01627 break;
01628
01629 case Q921_DL_DATA:
01630 res = Q921EnqueueI(trunk,
01631 trunk->sapi,
01632 Q921_COMMAND(trunk),
01633 link->tei,
01634 0,
01635 Mes,
01636 Size);
01637
01638 if(link->state < Q921_STATE_MULTIPLE_FRAME_ESTABLISHED) {
01639
01640
01641
01642 Q921EstablishDataLink(trunk, link->tei);
01643
01644
01645 Q921_SET_FLAG(link, Q921_FLAG_L3_INITIATED);
01646
01647
01648 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, link->tei);
01649 }
01650 break;
01651
01652 case Q921_DL_UNIT_DATA:
01653 res = Q921SendUN(trunk,
01654 trunk->sapi,
01655 Q921_COMMAND(trunk),
01656 Q921_TEI_BCAST,
01657 0,
01658 Mes,
01659 Size);
01660
01661 break;
01662
01663 default:
01664 break;
01665 }
01666
01667 return res;
01668 }
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685 static int Q921SendRR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf)
01686 {
01687 L2UCHAR mes[25];
01688
01689 #ifdef Q921_STATISTICS_VERBOSE
01690 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, Tei), Q921_STATS_SEND_RR);
01691 #endif
01692 return Q921SendS(trunk, Sapi, cr, Tei, pf, 0x00, mes, trunk->Q921HeaderSpace+4);
01693 }
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710 static int Q921SendRNR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf)
01711 {
01712 L2UCHAR mes[25];
01713
01714 #ifdef Q921_STATISTICS_VERBOSE
01715 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, Tei), Q921_STATS_SEND_RNR);
01716 #endif
01717 return Q921SendS(trunk, Sapi, cr, Tei, pf, 0x01, mes, trunk->Q921HeaderSpace+4);
01718 }
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735 static int Q921SendREJ(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf)
01736 {
01737 L2UCHAR mes[25];
01738
01739 #ifdef Q921_STATISTICS_VERBOSE
01740 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, Tei), Q921_STATS_SEND_REJ);
01741 #endif
01742 return Q921SendS(trunk, Sapi, cr, Tei, pf, 0x03, mes, trunk->Q921HeaderSpace+4);
01743 }
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760 static int Q921SendSABME(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf)
01761 {
01762 L2UCHAR mes[25];
01763
01764 #ifdef Q921_STATISTICS_VERBOSE
01765 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, Tei), Q921_STATS_SEND_SABME);
01766 #endif
01767 return Q921SendU(trunk, Sapi, cr, Tei, pf, 0x0f, mes, trunk->Q921HeaderSpace+3);
01768 }
01769
01770
01777 int Q921Start(L2TRUNK trunk)
01778 {
01779 int x, numlinks = Q921_IS_PTMP_NT(trunk) ? Q921_TEI_MAX : 1;
01780 struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk);
01781
01782 if(trunk->initialized != INITIALIZED_MAGIC)
01783 return 0;
01784
01785 memset(trunk->context, 0, numlinks * sizeof(struct Q921_Link));
01786
01787
01788 for(x = 0; x <= numlinks; x++) {
01789 link = Q921_LINK_CONTEXT(trunk, x);
01790
01791 link->state = Q921_STATE_TEI_UNASSIGNED;
01792 link->tei = 0;
01793
01794
01795 MFIFOCreate(link->UIFrameQueue, Q921MAXHDLCSPACE, 10);
01796 MFIFOCreate(link->IFrameQueue, Q921MAXHDLCSPACE, 10);
01797 MFIFOCreate(link->IFrameResendQueue, Q921MAXHDLCSPACE, 10);
01798 }
01799
01800 if(Q921_IS_PTMP_TE(trunk)) {
01801 link->state = Q921_STATE_TEI_UNASSIGNED;
01802 link->tei = 0;
01803 }
01804 else if(Q921_IS_PTMP_NT(trunk)) {
01805 link = Q921_TRUNK_CONTEXT(trunk);
01806
01807 link->state = Q921_STATE_TEI_ASSIGNED;
01808 link->tei = trunk->tei;
01809
01810
01811 memset(trunk->tei_map, 0, Q921_TEI_MAX + 1);
01812 }
01813 else {
01814 link->state = Q921_STATE_TEI_ASSIGNED;
01815 link->tei = trunk->tei;
01816 }
01817
01818 Q921Log(trunk, Q921_LOG_DEBUG, "Starting trunk %p (sapi: %d, tei: %d, mode: %s %s)\n",
01819 trunk,
01820 trunk->sapi,
01821 link->tei,
01822 Q921_IS_PTMP(trunk) ? "PTMP" : "PTP",
01823 Q921_IS_TE(trunk) ? "TE" : "NT");
01824
01825 if(Q921_IS_PTP(trunk)) {
01826 Q921Log(trunk, Q921_LOG_DEBUG, "Sending SABME\n");
01827
01828 return Q921SendSABME(trunk,
01829 trunk->sapi,
01830 Q921_COMMAND(trunk),
01831 link->tei,
01832 1);
01833
01834 } else if(Q921_IS_PTMP_NT(trunk)) {
01835
01836 Q921Log(trunk, Q921_LOG_DEBUG, "Revoking all TEIs\n");
01837
01838 return Q921TeiSendRemoveRequest(trunk, Q921_TEI_BCAST);
01839 } else {
01840
01841 Q921Log(trunk, Q921_LOG_DEBUG, "Requesting TEI\n");
01842
01843 return Q921TeiSendAssignRequest(trunk);
01844 }
01845 }
01846
01847
01856 int Q921Stop(L2TRUNK trunk)
01857 {
01858 struct Q921_Link *link;
01859 int x, numlinks;
01860
01861 if(!trunk)
01862 return -1;
01863
01864 link = Q921_TRUNK_CONTEXT(trunk);
01865 numlinks = Q921_IS_PTMP_NT(trunk) ? Q921_TEI_MAX : 1;
01866
01867 if(Q921_IS_STOPPED(link))
01868 return 0;
01869
01870
01871 if(Q921_IS_PTMP_TE(trunk)) {
01872
01873 Q921TeiSendVerifyRequest(trunk);
01874
01875
01876 link->tei = 0;
01877 }
01878
01879
01880 for(x = 0; x <= numlinks; x++) {
01881 Q921T200TimerStop(trunk, x);
01882 Q921T203TimerStop(trunk, x);
01883 Q921T201TimerStop(trunk, x);
01884
01885
01886 Q921ChangeState(trunk, Q921_STATE_STOPPED, x);
01887
01888
01889 MFIFOClear(link->UIFrameQueue);
01890 MFIFOClear(link->IFrameQueue);
01891 MFIFOClear(link->IFrameResendQueue);
01892 }
01893 Q921T202TimerStop(trunk);
01894
01895
01896 MFIFOClear(trunk->HDLCInQueue);
01897
01898 return 0;
01899 }
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917 static int Q921SendDM(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf)
01918 {
01919 L2UCHAR mes[25];
01920
01921 #ifdef Q921_STATISTICS_VERBOSE
01922 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, Tei), Q921_STATS_SEND_DM);
01923 #endif
01924 return Q921SendU(trunk, Sapi, cr, Tei, pf, 0x03, mes, trunk->Q921HeaderSpace+3);
01925 }
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942 static int Q921SendDISC(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf)
01943 {
01944 L2UCHAR mes[25];
01945
01946 #ifdef Q921_STATISTICS_VERBOSE
01947 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, Tei), Q921_STATS_SEND_DISC);
01948 #endif
01949 return Q921SendU(trunk, Sapi, cr, Tei, pf, 0x08, mes, trunk->Q921HeaderSpace+3);
01950 }
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967 static int Q921SendUA(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf)
01968 {
01969 L2UCHAR mes[25];
01970
01971 #ifdef Q921_STATISTICS_VERBOSE
01972 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, Tei), Q921_STATS_SEND_UA);
01973 #endif
01974 return Q921SendU(trunk, Sapi, cr, Tei, pf, 0x0c, mes, trunk->Q921HeaderSpace+3);
01975 }
01976
01977 static int Q921SendUN(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf, L2UCHAR *mes, L2INT size)
01978 {
01979 #ifdef Q921_STATISTICS_VERBOSE
01980 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, Tei), Q921_STATS_SEND_UN);
01981 #endif
01982 return Q921SendU(trunk, Sapi, cr, Tei, pf, 0x00, mes, size+trunk->Q921HeaderSpace+3);
01983 }
01984
01985
01994 static int Q921ProcSABME(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
01995 {
01996 L2UCHAR pf = (mes[2] & 0x10) >> 4;
01997 L2UCHAR tei = (mes[1] & 0xfe) >> 1;
01998 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
01999
02000 switch(link->state) {
02001 case Q921_STATE_TEI_ASSIGNED:
02002
02003 Q921SendUA(trunk,
02004 trunk->sapi,
02005 Q921_RESPONSE(trunk),
02006 tei, pf);
02007
02008
02009 link->vr=0;
02010 link->vs=0;
02011 link->va=0;
02012
02013
02014 Q921Tx23Proc(trunk, Q921_DL_ESTABLISH, tei, NULL, 0);
02015
02016
02017 Q921T203TimerStart(trunk, tei);
02018
02019
02020 Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei);
02021 break;
02022
02023 case Q921_STATE_AWAITING_ESTABLISHMENT:
02024
02025 Q921SendUA(trunk,
02026 trunk->sapi,
02027 Q921_RESPONSE(trunk),
02028 tei, pf);
02029
02030
02031 break;
02032
02033 case Q921_STATE_AWAITING_RELEASE:
02034
02035 Q921SendDM(trunk,
02036 trunk->sapi,
02037 Q921_RESPONSE(trunk),
02038 tei, pf);
02039
02040
02041 break;
02042
02043 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
02044 case Q921_STATE_TIMER_RECOVERY:
02045
02046 Q921SendUA(trunk,
02047 trunk->sapi,
02048 Q921_RESPONSE(trunk),
02049 tei, pf);
02050
02051
02052 Q921ResetExceptionConditions(trunk, tei);
02053
02054
02055
02056
02057 if(link->vs != link->va) {
02058
02059 MFIFOClear(link->IFrameQueue);
02060
02061
02062 Q921Tx23Proc(trunk, Q921_DL_ESTABLISH, tei, NULL, 0);
02063 }
02064
02065
02066 link->vr=0;
02067 link->vs=0;
02068 link->va=0;
02069
02070
02071 Q921T200TimerStop(trunk, tei);
02072 Q921T203TimerStart(trunk, tei);
02073
02074
02075 if(link->state == Q921_STATE_TIMER_RECOVERY)
02076 Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei);
02077 break;
02078
02079 default:
02080 break;
02081 }
02082
02083 return 1;
02084 }
02085
02086
02095 static int Q921ProcDM(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
02096 {
02097 L2UCHAR pf = (mes[2] & 0x10) >> 4;
02098 L2UCHAR tei = (mes[1] & 0xfe) >> 1;
02099 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
02100
02101 switch(link->state) {
02102 case Q921_STATE_TEI_ASSIGNED:
02103 if(!pf) {
02104
02105 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02106 }
02107 break;
02108
02109 case Q921_STATE_AWAITING_ESTABLISHMENT:
02110 case Q921_STATE_AWAITING_RELEASE:
02111 if(pf) {
02112 if(link->state == Q921_STATE_AWAITING_ESTABLISHMENT) {
02113
02114 MFIFOClear(link->IFrameQueue);
02115 }
02116
02117
02118 Q921Tx23Proc(trunk, Q921_DL_RELEASE, tei, NULL, 0);
02119
02120
02121 Q921T200TimerStop(trunk, tei);
02122
02123
02124 Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, tei);
02125 }
02126 break;
02127
02128 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
02129 if(pf) {
02130
02131
02132
02133 } else {
02134
02135
02136
02137 Q921EstablishDataLink(trunk, tei);
02138
02139
02140 Q921_CLEAR_FLAG(link, Q921_FLAG_L3_INITIATED);
02141
02142
02143 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02144 }
02145 break;
02146
02147 case Q921_STATE_TIMER_RECOVERY:
02148 if(pf) {
02149
02150 } else {
02151
02152 }
02153
02154
02155 Q921EstablishDataLink(trunk, tei);
02156
02157
02158 Q921_CLEAR_FLAG(link, Q921_FLAG_L3_INITIATED);
02159
02160
02161 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02162 break;
02163
02164 default:
02165 break;
02166 }
02167
02168 return 1;
02169 }
02170
02179 static int Q921ProcUA(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
02180 {
02181 L2UCHAR pf = (mes[2] & 0x10) >> 4;
02182 L2UCHAR tei = (mes[1] & 0xfe) >> 1;
02183 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
02184
02185 switch(link->state) {
02186 case Q921_STATE_TEI_ASSIGNED:
02187 case Q921_STATE_TIMER_RECOVERY:
02188
02189 Q921Log(trunk, Q921_LOG_ERROR, "Received UA frame in invalid state\n");
02190 break;
02191
02192 case Q921_STATE_AWAITING_ESTABLISHMENT:
02193 if(pf) {
02194
02195 if(Q921_CHECK_FLAG(link, Q921_FLAG_L3_INITIATED)) {
02196 link->vr = 0;
02197
02198
02199 Q921Tx23Proc(trunk, Q921_DL_ESTABLISH_CONFIRM, tei, NULL, 0);
02200
02201 } else if(link->vs != link->va) {
02202
02203
02204 MFIFOClear(link->IFrameQueue);
02205
02206
02207 Q921Tx23Proc(trunk, Q921_DL_ESTABLISH, tei, NULL, 0);
02208 }
02209
02210
02211 Q921T200TimerStop(trunk, tei);
02212 Q921T203TimerStart(trunk, tei);
02213
02214 link->vs = 0;
02215 link->va = 0;
02216
02217
02218 Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei);
02219 } else {
02220
02221 Q921Log(trunk, Q921_LOG_ERROR, "Received UA frame is not a response to a request\n");
02222
02223
02224 }
02225 break;
02226
02227 case Q921_STATE_AWAITING_RELEASE:
02228 if(pf) {
02229
02230 Q921Tx23Proc(trunk, Q921_DL_RELEASE_CONFIRM, tei, NULL, 0);
02231
02232
02233 Q921T200TimerStop(trunk, tei);
02234
02235
02236 Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, tei);
02237 } else {
02238
02239 Q921Log(trunk, Q921_LOG_ERROR, "Received UA frame is not a response to a request\n");
02240
02241
02242 }
02243 break;
02244
02245 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
02246
02247 Q921Log(trunk, Q921_LOG_ERROR, "Received UA frame in invalid state\n");
02248
02249
02250 break;
02251
02252 default:
02253 break;
02254 }
02255
02256 return 1;
02257 }
02258
02259
02268 static int Q921ProcDISC(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
02269 {
02270 L2UCHAR pf = (mes[2] & 0x10) >> 4;
02271 L2UCHAR tei = (mes[1] & 0xfe) >> 1;
02272 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
02273
02274 switch(link->state) {
02275 case Q921_STATE_TEI_ASSIGNED:
02276 case Q921_STATE_AWAITING_ESTABLISHMENT:
02277
02278 Q921SendDM(trunk,
02279 trunk->sapi,
02280 Q921_RESPONSE(trunk),
02281 tei, pf);
02282
02283
02284 break;
02285
02286 case Q921_STATE_AWAITING_RELEASE:
02287 Q921SendUA(trunk,
02288 trunk->sapi,
02289 Q921_RESPONSE(trunk),
02290 tei, pf);
02291
02292
02293 break;
02294
02295 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
02296 case Q921_STATE_TIMER_RECOVERY:
02297
02298 MFIFOClear(link->IFrameQueue);
02299
02300
02301 Q921SendUA(trunk,
02302 trunk->sapi,
02303 Q921_RESPONSE(trunk),
02304 tei, pf);
02305
02306
02307 Q921Tx23Proc(trunk, Q921_DL_RELEASE, tei, NULL, 0);
02308
02309
02310 Q921T200TimerStop(trunk, tei);
02311
02312 if(link->state == Q921_STATE_MULTIPLE_FRAME_ESTABLISHED) {
02313
02314 Q921T203TimerStop(trunk, tei);
02315 }
02316
02317
02318 Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, tei);
02319 break;
02320
02321 default:
02322 Q921Log(trunk, Q921_LOG_ERROR, "Invalid DISC received in state \"%s\" (%d)", Q921State2Name(link->state), link->state);
02323 break;
02324 }
02325
02326 return 1;
02327 }
02328
02329
02338 static int Q921ProcRR(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
02339 {
02340 L2UCHAR cr = (mes[0] & 0x02) >> 1;
02341 L2UCHAR pf = mes[3] & 0x01;
02342 L2UCHAR nr = (mes[3] >> 1);
02343
02344 L2UCHAR tei = (mes[1] & 0xfe) >> 1;
02345 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
02346
02347 switch(link->state) {
02348 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
02349
02350 Q921_CLEAR_FLAG(link, Q921_FLAG_PEER_RECV_BUSY);
02351
02352 if (Q921_IS_COMMAND(trunk, cr)) {
02353 if(pf) {
02354
02355 Q921SendEnquiryResponse(trunk, tei);
02356 }
02357 } else {
02358 if(pf) {
02359
02360 }
02361 }
02362
02363
02364 if(link->va <= nr && nr <= link->vs) {
02365
02366 if(nr == link->vs) {
02367
02368 link->va = nr;
02369
02370
02371 Q921T200TimerStop(trunk, tei);
02372 Q921T203TimerReset(trunk, tei);
02373
02374 } else if(nr == link->va) {
02375
02376
02377
02378 } else {
02379
02380 link->va = nr;
02381
02382
02383 Q921T200TimerReset(trunk, tei);
02384 }
02385
02386
02387 } else {
02388
02389 Q921NrErrorRecovery(trunk, tei);
02390
02391
02392 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02393 }
02394 break;
02395
02396 case Q921_STATE_TIMER_RECOVERY:
02397
02398 Q921_CLEAR_FLAG(link, Q921_FLAG_PEER_RECV_BUSY);
02399
02400
02401 if(Q921_IS_COMMAND(trunk, cr) && pf) {
02402
02403 Q921SendEnquiryResponse(trunk, tei);
02404 }
02405
02406
02407 if(link->va <= nr && nr <= link->vs) {
02408
02409 link->va = nr;
02410
02411 if(!Q921_IS_COMMAND(trunk, cr) && pf) {
02412
02413 Q921T200TimerStop(trunk, tei);
02414 Q921T203TimerStart(trunk, tei);
02415
02416
02417 Q921InvokeRetransmission(trunk, tei, nr);
02418
02419
02420 Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei);
02421 }
02422
02423 } else {
02424
02425 Q921NrErrorRecovery(trunk, tei);
02426
02427
02428 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02429 }
02430 break;
02431
02432 default:
02433 break;
02434 }
02435 return 1;
02436 }
02437
02438
02447 static int Q921ProcREJ(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
02448 {
02449 L2UCHAR cr = (mes[0] & 0x02) >> 1;
02450 L2UCHAR pf = mes[3] & 0x01;
02451 L2UCHAR nr = (mes[3] >> 1);
02452
02453 L2UCHAR tei = (mes[1] & 0xfe) >> 1;
02454 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
02455
02456 switch(link->state) {
02457 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
02458
02459 Q921_CLEAR_FLAG(link, Q921_FLAG_PEER_RECV_BUSY);
02460
02461
02462 if(Q921_IS_COMMAND(trunk, cr)) {
02463 if(pf) {
02464
02465 Q921SendEnquiryResponse(trunk, tei);
02466 }
02467 } else {
02468 if(pf) {
02469
02470 }
02471 }
02472
02473
02474 if(link->va <= nr && nr <= link->vs) {
02475
02476
02477 link->va = nr;
02478
02479
02480 Q921T200TimerStop(trunk, tei);
02481 Q921T203TimerStart(trunk, tei);
02482
02483
02484 Q921InvokeRetransmission(trunk, tei, nr);
02485
02486
02487 } else {
02488
02489 Q921NrErrorRecovery(trunk, tei);
02490
02491
02492 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02493 }
02494 break;
02495
02496 case Q921_STATE_TIMER_RECOVERY:
02497
02498 Q921_CLEAR_FLAG(link, Q921_FLAG_PEER_RECV_BUSY);
02499
02500
02501 if(Q921_IS_COMMAND(trunk, cr) && pf) {
02502
02503 Q921SendEnquiryResponse(trunk, tei);
02504 }
02505
02506
02507 if(link->va <= nr && nr <= link->vs) {
02508
02509
02510 link->va = nr;
02511
02512 if(!Q921_IS_COMMAND(trunk, cr) && pf) {
02513
02514 Q921T200TimerStop(trunk, tei);
02515 Q921T203TimerStart(trunk, tei);
02516
02517
02518 Q921InvokeRetransmission(trunk, tei, nr);
02519
02520
02521 Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei);
02522 }
02523
02524 } else {
02525
02526 Q921NrErrorRecovery(trunk, tei);
02527
02528
02529 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02530 }
02531 break;
02532
02533 default:
02534 break;
02535 }
02536
02537 return 1;
02538 }
02539
02540
02549 static int Q921ProcRNR(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
02550 {
02551 L2UCHAR cr = (mes[0] & 0x02) >> 1;
02552 L2UCHAR pf = mes[3] & 0x01;
02553 L2UCHAR nr = (mes[3] >> 1);
02554
02555 L2UCHAR tei = (mes[1] & 0xfe) >> 1;
02556 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
02557
02558 switch(link->state) {
02559 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
02560
02561 Q921_SET_FLAG(link, Q921_FLAG_PEER_RECV_BUSY);
02562
02563
02564 if(Q921_IS_COMMAND(trunk, cr)) {
02565 if(pf) {
02566
02567 Q921SendEnquiryResponse(trunk, tei);
02568 }
02569 } else {
02570 if(pf) {
02571
02572 }
02573 }
02574
02575
02576 if(link->va <= nr && nr <= link->vs) {
02577
02578
02579 link->va = nr;
02580
02581
02582 Q921T200TimerReset(trunk, tei);
02583 Q921T203TimerStop(trunk, tei);
02584
02585
02586 } else {
02587
02588 Q921NrErrorRecovery(trunk, tei);
02589
02590
02591 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02592 }
02593 break;
02594
02595 case Q921_STATE_TIMER_RECOVERY:
02596
02597 Q921_SET_FLAG(link, Q921_FLAG_PEER_RECV_BUSY);
02598
02599
02600 if(Q921_IS_COMMAND(trunk, cr) && pf) {
02601
02602 Q921SendEnquiryResponse(trunk, tei);
02603 }
02604
02605
02606 if(link->va <= nr && nr <= link->vs) {
02607
02608
02609 link->va = nr;
02610
02611 if(!Q921_IS_COMMAND(trunk, cr) && pf) {
02612
02613 Q921T200TimerReset(trunk, tei);
02614
02615
02616 Q921InvokeRetransmission(trunk, tei, nr);
02617
02618
02619 Q921ChangeState(trunk, Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, tei);
02620 }
02621
02622 } else {
02623
02624 Q921NrErrorRecovery(trunk, tei);
02625
02626
02627 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02628 }
02629 break;
02630
02631 default:
02632 break;
02633 }
02634
02635 return 1;
02636 }
02637
02638 #if 0
02639 static int Q921SetReceiverBusy(L2TRUNK trunk)
02640 {
02641 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
02642
02643 switch(link->state) {
02644 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
02645 if(!Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) {
02646
02647 Q921_SET_FLAG(link, Q921_FLAG_RECV_BUSY);
02648
02649
02650 Q921SendRR(trunk, trunk->sapi, Q921_RESPONSE(trunk), link->tei, 0);
02651
02652
02653 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
02654 }
02655 break;
02656
02657 case Q921_STATE_TIMER_RECOVERY:
02658 if(!Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) {
02659
02660 Q921_SET_FLAG(link, Q921_FLAG_RECV_BUSY);
02661
02662
02663 Q921SendRNR(trunk, trunk->sapi, Q921_RESPONSE(trunk), link->tei, 0);
02664
02665
02666 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
02667 }
02668 break;
02669
02670 default:
02671 break;
02672 }
02673
02674 return 0;
02675 }
02676
02677 static int Q921ClearReceiverBusy(L2TRUNK trunk)
02678 {
02679 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
02680
02681 switch(link->state) {
02682 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
02683 case Q921_STATE_TIMER_RECOVERY:
02684 if(Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) {
02685
02686 Q921_CLEAR_FLAG(link, Q921_FLAG_RECV_BUSY);
02687
02688
02689 Q921SendRNR(trunk, trunk->sapi, Q921_RESPONSE(trunk), link->tei, 0);
02690
02691
02692 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
02693 }
02694 break;
02695
02696 default:
02697 break;
02698 }
02699
02700 return 0;
02701 }
02702 #endif
02703
02704 static int Q921ProcIFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
02705 {
02706
02707
02708
02709 L2UCHAR tei = (mes[1] & 0xfe) >> 1;
02710 L2UCHAR pf = mes[3] & 0x01;
02711 L2UCHAR nr = mes[3] >> 1;
02712 L2UCHAR ns = mes[2] >> 1;
02713 L2UCHAR discard = 0;
02714 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
02715
02716
02717 if(link->state < Q921_STATE_MULTIPLE_FRAME_ESTABLISHED) {
02718 Q921Log(trunk, Q921_LOG_NOTICE, "I frame in invalid state ignored\n");
02719 return 0;
02720 }
02721
02722 #ifdef Q921_STATISTICS_VERBOSE
02723 Q921StatsIncrementCounter(link, Q921_STATS_RECV_I);
02724 #endif
02725
02726
02727 if(Q921_CHECK_FLAG(link, Q921_FLAG_RECV_BUSY)) {
02728
02729 discard = 1;
02730
02731 if(pf) {
02732
02733 Q921SendRNR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 1);
02734
02735
02736 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
02737 }
02738 }
02739 else {
02740 if(ns != link->vr) {
02741
02742 discard = 1;
02743
02744 if(Q921_CHECK_FLAG(link, Q921_FLAG_REJECT) && pf) {
02745
02746
02747 Q921SendRR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 1);
02748
02749
02750 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
02751 }
02752 else if(!Q921_CHECK_FLAG(link, Q921_FLAG_REJECT)){
02753
02754
02755 Q921_SET_FLAG(link, Q921_FLAG_REJECT);
02756
02757
02758 Q921SendREJ(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, pf);
02759
02760
02761 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
02762 }
02763 }
02764 else {
02765
02766 Q921_INC_COUNTER(link->vr);
02767
02768
02769 Q921_CLEAR_FLAG(link, Q921_FLAG_REJECT);
02770
02771
02772 Q921Tx23Proc(trunk, Q921_DL_DATA, tei, mes, size);
02773
02774 if(pf) {
02775
02776 Q921SendRR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 1);
02777
02778
02779 Q921_CLEAR_FLAG(link, Q921_FLAG_ACK_PENDING);
02780 }
02781 else if(!Q921_CHECK_FLAG(link, Q921_FLAG_ACK_PENDING)) {
02782
02783
02784
02785 Q921SendRR(trunk, trunk->sapi, Q921_RESPONSE(trunk), tei, 0);
02786
02787
02788 Q921_SET_FLAG(link, Q921_FLAG_ACK_PENDING);
02789 }
02790 }
02791 }
02792
02793
02794 switch(link->state) {
02795 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
02796 if(link->va <= nr && nr <= link->vs) {
02797 if(Q921_CHECK_FLAG(link, Q921_FLAG_PEER_RECV_BUSY)) {
02798 link->va = nr;
02799 }
02800 else if(nr == link->vs) {
02801
02802 link->va = nr;
02803
02804
02805 Q921T200TimerStop(trunk, tei);
02806 Q921T203TimerReset(trunk, tei);
02807 }
02808 else if(nr != link->va) {
02809
02810 link->va = nr;
02811
02812
02813 Q921T200TimerReset(trunk, tei);
02814 }
02815
02816
02817 if(Q921_IS_NT(trunk)) {
02818 Q921TM01TimerReset(trunk, tei);
02819 }
02820 }
02821 else {
02822
02823 Q921NrErrorRecovery(trunk, tei);
02824
02825
02826 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02827 }
02828 break;
02829
02830 case Q921_STATE_TIMER_RECOVERY:
02831 if(link->va <= nr && nr <= link->vs) {
02832
02833 link->va = nr;
02834
02835
02836 if(Q921_IS_NT(trunk)) {
02837 Q921TM01TimerReset(trunk, tei);
02838 }
02839 }
02840 else {
02841
02842 Q921NrErrorRecovery(trunk, tei);
02843
02844
02845 Q921ChangeState(trunk, Q921_STATE_AWAITING_ESTABLISHMENT, tei);
02846 }
02847 break;
02848
02849 default:
02850 break;
02851 }
02852
02853 return 0;
02854 }
02855
02856
02857 static int Q921ProcSFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
02858 {
02859 L2UCHAR sv = (mes[2] & 0x0c) >> 2;
02860
02861
02862 L2INT res = -1;
02863 #ifdef Q921_STATISTICS_VERBOSE
02864 L2UCHAR tei = (mes[1] & 0xfe) >> 1;
02865
02866 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, tei), Q921_STATS_RECV_S);
02867 #endif
02868
02869 switch(sv) {
02870 case 0x00:
02871 res = Q921ProcRR(trunk, mes, size);
02872 break;
02873
02874 case 0x02:
02875 res = Q921ProcRNR(trunk, mes, size);
02876 break;
02877
02878 case 0x04:
02879 res = Q921ProcREJ(trunk, mes, size);
02880 break;
02881
02882 default:
02883 #ifdef Q921_STATISTICS_VERBOSE
02884 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, tei), Q921_STATS_RECV_INVALID_S);
02885 #endif
02886 Q921Log(trunk, Q921_LOG_ERROR, "Invalid S frame type %d\n", sv);
02887 break;
02888 }
02889
02890 return res;
02891 }
02892
02893
02894
02895 static int Q921ProcUFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
02896 {
02897 L2UCHAR m = (mes[2] & 0xe0) >> 3 | (mes[2] & 0x0c) >> 2;
02898
02899 L2INT res = -1;
02900 #ifdef Q921_STATISTICS_VERBOSE
02901 L2UCHAR tei = (mes[1] & 0xfe) >> 1;
02902
02903 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, tei), Q921_STATS_RECV_U);
02904 #endif
02905
02906 switch(m) {
02907 case 0x00:
02908 if(mes[3] == Q921_LAYER_ENT_ID_TEI)
02909 {
02910 if(!Q921_IS_PTMP(trunk)) {
02911
02912 return res;
02913 }
02914
02915 switch(mes[6]) {
02916 case Q921_TEI_ID_REQUEST:
02917 res = Q921TeiProcAssignRequest(trunk, mes, size);
02918 break;
02919
02920 case Q921_TEI_ID_ASSIGNED:
02921 case Q921_TEI_ID_DENIED:
02922 res = Q921TeiProcAssignResponse(trunk, mes, size);
02923 break;
02924
02925 case Q921_TEI_ID_CHECKREQ:
02926 res = Q921TeiProcCheckRequest(trunk, mes, size);
02927 break;
02928
02929 case Q921_TEI_ID_CHECKRESP:
02930 res = Q921TeiProcCheckResponse(trunk, mes, size);
02931 break;
02932
02933 case Q921_TEI_ID_REMOVE:
02934 res = Q921TeiProcRemoveRequest(trunk, mes, size);
02935 break;
02936
02937 case Q921_TEI_ID_VERIFY:
02938 res = Q921TeiProcVerifyRequest(trunk, mes, size);
02939 break;
02940
02941 default:
02942 Q921Log(trunk, Q921_LOG_ERROR, "Invalid UN message from TEI management/endpoint\n");
02943 break;
02944 }
02945 }
02946 else if(mes[3] == Q921_LAYER_ENT_ID_Q931) {
02947
02948 Q921Log(trunk, Q921_LOG_DEBUG, "UI Frame for Layer 3 received\n");
02949
02950 res = Q921Tx23Proc(trunk, Q921_DL_UNIT_DATA, 0, mes, size);
02951 }
02952 break;
02953
02954 case 0x03:
02955 res = Q921ProcDM(trunk, mes, size);
02956 break;
02957
02958 case 0x08:
02959 res = Q921ProcDISC(trunk, mes, size);
02960 break;
02961
02962 case 0x0c:
02963 res = Q921ProcUA(trunk, mes, size);
02964 break;
02965
02966 case 0x0f:
02967 res = Q921ProcSABME(trunk, mes, size);
02968 break;
02969
02970 case 0x11:
02971 case 0x17:
02972 res = 0;
02973 break;
02974
02975 default:
02976 #ifdef Q921_STATISTICS_VERBOSE
02977 Q921StatsIncrementCounter(Q921_LINK_CONTEXT(trunk, tei), Q921_STATS_RECV_INVALID_U);
02978 #endif
02979 Q921Log(trunk, Q921_LOG_ERROR, "Invalid U frame type: %d\n", m);
02980 break;
02981 }
02982
02983 return res;
02984 }
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005 int Q921Rx12(L2TRUNK trunk)
03006 {
03007 L2INT size;
03008 L2UCHAR *smes = MFIFOGetMesPtr(trunk->HDLCInQueue, &size);
03009
03010 if(smes)
03011 {
03012 struct Q921_Link *link;
03013 L2UCHAR sapi, tei;
03014 L2UCHAR *mes;
03015 L2INT rs;
03016
03017 rs = size - trunk->Q921HeaderSpace;
03018 mes = &smes[trunk->Q921HeaderSpace];
03019
03020 Q921LogMesg(trunk, Q921_LOG_DEBUG, 1, mes, rs, "New packet received (%d bytes)", rs);
03021
03022
03023 sapi = (mes[0] & 0xfc) >> 2;
03024 tei = (mes[1] & 0xfe) >> 1;
03025 link = Q921_LINK_CONTEXT(trunk, tei);
03026
03027 if(Q921_IS_PTMP_TE(trunk) && (
03028 (link->state >= Q921_STATE_TEI_ASSIGNED && tei != link->tei && tei != Q921_TEI_BCAST) ||
03029 (link->state == Q921_STATE_TEI_UNASSIGNED && tei != Q921_TEI_BCAST)))
03030 {
03031
03032 goto out;
03033 }
03034
03035 if((mes[2] & 0x01) == 0x00) {
03036 Q921ProcIFrame(trunk, mes, rs);
03037 }
03038 else if((mes[2] & 0x03) == 0x01) {
03039 Q921ProcSFrame(trunk, mes, rs);
03040 }
03041 else if((mes[2] & 0x03) == 0x03) {
03042 Q921ProcUFrame(trunk, mes, rs);
03043 }
03044 else {
03045 Q921Log(trunk, Q921_LOG_ERROR, "Invalid frame type: %d\n", (int)(mes[2] & 0x03));
03046
03047 }
03048
03049 out:
03050 MFIFOKillNext(trunk->HDLCInQueue);
03051
03052 return 1;
03053 }
03054
03055 return 0;
03056 }
03057
03058
03059
03060
03070 void Q921SetLogCB(L2TRUNK trunk, Q921LogCB_t func, void *priv)
03071 {
03072 if(!trunk)
03073 return;
03074
03075 trunk->Q921LogProc = func;
03076 trunk->PrivateDataLog = priv;
03077 }
03078
03087 void Q921SetLogLevel(L2TRUNK trunk, Q921LogLevel_t level)
03088 {
03089 if(!trunk)
03090 return;
03091
03092 if (level < Q921_LOG_NONE) {
03093 level = Q921_LOG_NONE;
03094 } else if (level > Q921_LOG_DEBUG) {
03095 level = Q921_LOG_DEBUG;
03096 }
03097
03098 trunk->loglevel = level;
03099 }
03100
03101
03111 static int Q921ChangeState(L2TRUNK trunk, Q921State_t state, L2UCHAR tei)
03112 {
03113 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
03114 Q921State_t oldstate = link->state;
03115 int res = 0;
03116
03117 Q921Log(trunk, Q921_LOG_DEBUG, "Changing state from \"%s\" (%d) to \"%s\" (%d) for TEI %d\n",
03118 Q921State2Name(oldstate), oldstate,
03119 Q921State2Name(state), state,
03120 tei);
03121
03122
03123
03124
03125 switch(state) {
03126 case Q921_STATE_MULTIPLE_FRAME_ESTABLISHED:
03127
03128 if(Q921_IS_NT(trunk)) {
03129 Q921TM01TimerStart(trunk, tei);
03130 }
03131 break;
03132
03133 default:
03134 break;
03135 }
03136
03137
03138
03139
03140 switch(oldstate) {
03141 case Q921_STATE_STOPPED:
03142
03143 switch(state) {
03144 case Q921_STATE_TEI_UNASSIGNED:
03145 if(Q921_IS_PTMP_TE(trunk)) {
03146 res = Q921TeiSendAssignRequest(trunk);
03147 }
03148 break;
03149
03150 case Q921_STATE_TEI_ASSIGNED:
03151 if(Q921_IS_PTMP_NT(trunk)) {
03152 res = Q921TeiSendRemoveRequest(trunk, Q921_TEI_BCAST);
03153 }
03154 break;
03155
03156 default:
03157 break;
03158 }
03159 break;
03160
03161 default:
03162 break;
03163 }
03164
03165 link->state = state;
03166
03167 Q921Log(trunk, Q921_LOG_DEBUG, "Q921ChangeState() returns %d, new state is \"%s\" (%d) for TEI %d\n", res, Q921State2Name(state), state, tei);
03168
03169 #ifdef Q921_STATISTICS
03170
03171 Q921StatsIncrementCounter(link, state);
03172 #endif
03173 return res;
03174 }
03175
03176
03177
03178
03179
03180 static int Q921TeiSend(L2TRUNK trunk, L2UCHAR type, L2USHORT ri, L2UCHAR ai)
03181 {
03182 L2UCHAR mes[10];
03183 L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk);
03184
03185 mes[offset++] = Q921_LAYER_ENT_ID_TEI;
03186 mes[offset++] = (ri & 0xff00) >> 8;
03187 mes[offset++] = ri & 0xff;
03188 mes[offset++] = type;
03189 mes[offset++] = ai << 1 | 0x01;
03190
03191 #ifdef Q921_STATISTICS_VERBOSE
03192
03193 #endif
03194
03195 return Q921SendU(trunk, Q921_SAPI_TEI, Q921_COMMAND(trunk), Q921_TEI_BCAST, 0, 0x00, mes, offset);
03196 }
03197
03198
03207 static int Q921TeiSendAssignRequest(L2TRUNK trunk)
03208 {
03209 struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk);
03210 L2INT res;
03211
03212 if (!Q921_IS_PTMP_TE(trunk))
03213 return 0;
03214
03215 link->ri = (L2USHORT)(random() % 0xffff);
03216
03217
03218 res = Q921TeiSend(trunk, Q921_TEI_ID_REQUEST, link->ri, Q921_TEI_BCAST);
03219
03220
03221 Q921T202TimerStart(trunk);
03222
03223 return res;
03224 }
03225
03226
03237 static int Q921TeiProcAssignResponse(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
03238 {
03239 struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk);
03240 L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk);
03241 L2USHORT ri = 0;
03242
03243 if (!Q921_IS_PTMP_TE(trunk))
03244 return 0;
03245
03246 ri = (mes[offset + 1] << 8) | mes[offset + 2];
03247
03248 if(ri != link->ri) {
03249
03250 return 0;
03251 }
03252
03253 switch(mes[offset + 3]) {
03254 case Q921_TEI_ID_ASSIGNED:
03255
03256 link->tei = mes[offset + 4] >> 1;
03257
03258 Q921Log(trunk, Q921_LOG_DEBUG, "Assigned TEI %d, setting state to TEI_ASSIGNED\n", link->tei);
03259
03260 Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, link->tei);
03261 break;
03262
03263 case Q921_TEI_ID_DENIED:
03264
03265 if ((mes[offset + 4] >> 1) == Q921_TEI_BCAST) {
03266
03267
03268
03269 } else {
03270
03271 }
03272
03273 Q921Log(trunk, Q921_LOG_DEBUG, "TEI assignment has been denied, reason: %s\n",
03274 ((mes[offset +4] >> 1) == Q921_TEI_BCAST) ? "No free TEIs available" : "Unknown");
03275
03276 Q921ChangeState(trunk, Q921_STATE_TEI_UNASSIGNED, link->tei);
03277 break;
03278
03279 default:
03280 return 0;
03281 }
03282
03283
03284 Q921T202TimerStop(trunk);
03285
03286 return 1;
03287 }
03288
03289
03298 static int Q921TeiSendVerifyRequest(L2TRUNK trunk)
03299 {
03300 struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk);
03301 L2INT res;
03302
03303 if (!Q921_IS_PTMP_TE(trunk))
03304 return 0;
03305
03306
03307 if (trunk->T202)
03308 return 0;
03309
03310
03311 res = Q921TeiSend(trunk, Q921_TEI_ID_VERIFY, link->ri, link->tei);
03312
03313
03314 Q921T202TimerStart(trunk);
03315
03316 return res;
03317 }
03318
03319
03330 static int Q921TeiProcCheckRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
03331 {
03332 struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk);
03333 L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk);
03334 L2UCHAR tei = (mes[offset + 4] >> 1);
03335 L2INT res = 0;
03336
03337 if (!Q921_IS_PTMP_TE(trunk))
03338 return 0;
03339
03340 Q921Log(trunk, Q921_LOG_DEBUG, "Received TEI Check request for TEI %d\n", tei);
03341
03342 if (tei == Q921_TEI_BCAST || tei == link->tei) {
03343
03344
03345
03346
03347
03348 res = Q921TeiSend(trunk, Q921_TEI_ID_CHECKRESP, link->ri, link->tei);
03349
03350 Q921T202TimerStop(trunk);
03351 }
03352
03353 return res;
03354 }
03355
03356
03367 static int Q921TeiProcRemoveRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
03368 {
03369 struct Q921_Link *link = Q921_TRUNK_CONTEXT(trunk);
03370 L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk);
03371 L2UCHAR tei = (mes[offset + 4] >> 1);
03372 L2INT res = 0;
03373
03374 if (!Q921_IS_PTMP_TE(trunk))
03375 return 0;
03376
03377 Q921Log(trunk, Q921_LOG_DEBUG, "Received TEI Remove request for TEI %d\n", tei);
03378
03379 if (tei == Q921_TEI_BCAST || tei == link->tei) {
03380
03381
03382
03383
03384
03385 link->tei = 0;
03386
03387
03388 Q921ChangeState(trunk, Q921_STATE_TEI_UNASSIGNED, link->tei);
03389
03390
03391 res = Q921TeiSendAssignRequest(trunk);
03392 }
03393 return res;
03394 }
03395
03396
03407 static int Q921TeiProcAssignRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
03408 {
03409 L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk);
03410 L2USHORT ri = 0;
03411 L2UCHAR tei = 0;
03412
03413 if (!Q921_IS_PTMP_NT(trunk))
03414 return 0;
03415
03416 ri = (mes[offset + 1] << 8) | mes[offset + 2];
03417 tei = mes[offset + 4] >> 1;
03418
03419 if(tei == Q921_TEI_BCAST) {
03420 int x;
03421
03422
03423 for(x = Q921_TEI_DYN_MIN, tei = 0; x <= Q921_TEI_MAX; x++) {
03424 if(!trunk->tei_map[x]) {
03425 tei = x;
03426 break;
03427 }
03428 }
03429 }
03430 else if(!(tei > 0 && tei < Q921_TEI_DYN_MIN)) {
03431
03432 Q921TeiSendDenyResponse(trunk, 0, ri);
03433
03434 return 0;
03435 }
03436
03437 if(!tei) {
03438
03439 Q921TeiSendDenyResponse(trunk, Q921_TEI_BCAST, ri);
03440 }
03441 else {
03442 struct Q921_Link *link = Q921_LINK_CONTEXT(trunk, tei);
03443
03444
03445 trunk->tei_map[tei] = 1;
03446
03447
03448 link->tei = tei;
03449
03450
03451 Q921ChangeState(trunk, Q921_STATE_TEI_ASSIGNED, tei);
03452
03453
03454 Q921TeiSendAssignedResponse(trunk, tei, ri);
03455
03456
03457 Q921T201TimerStart(trunk, tei);
03458 }
03459 return 0;
03460 }
03461
03471 static int Q921TeiSendCheckRequest(L2TRUNK trunk, L2UCHAR tei)
03472 {
03473 L2INT res = 0;
03474
03475 if (!Q921_IS_PTMP_NT(trunk))
03476 return 0;
03477
03478
03479 res = Q921TeiSend(trunk, Q921_TEI_ID_CHECKREQ, 0, tei);
03480
03481
03482 Q921T201TimerStart(trunk, tei);
03483
03484 return res;
03485 }
03486
03497 static int Q921TeiProcCheckResponse(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
03498 {
03499 struct Q921_Link *link;
03500 L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk);
03501 L2USHORT ri = 0;
03502 L2UCHAR tei = 0;
03503
03504 if (!Q921_IS_PTMP_NT(trunk))
03505 return 0;
03506
03507 ri = (mes[offset + 1] << 8) | mes[offset + 2];
03508 tei = mes[offset + 4] >> 1;
03509
03510
03511 Q921T201TimerStop(trunk, tei);
03512
03513
03514 link = Q921_LINK_CONTEXT(trunk, tei);
03515 link->N202 = 0;
03516
03517 if(!(tei > 0 && tei < Q921_TEI_MAX) || !trunk->tei_map[tei]) {
03518
03519
03520
03521 Q921TeiSendRemoveRequest(trunk, tei);
03522
03523
03524 Q921ChangeState(trunk, Q921_STATE_STOPPED, tei);
03525
03526
03527 memset(link, 0, sizeof(struct Q921_Link));
03528 } else {
03529
03530 Q921T201TimerStart(trunk, tei);
03531 }
03532
03533 return 0;
03534 }
03535
03536
03547 static int Q921TeiProcVerifyRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size)
03548 {
03549 L2UCHAR resp[25];
03550 L2UCHAR offset = Q921_UFRAME_DATA_OFFSET(trunk);
03551 L2UCHAR tei = 0;
03552
03553 if (!Q921_IS_PTMP_NT(trunk))
03554 return 0;
03555
03556 tei = mes[offset + 4] >> 1;
03557
03558
03559 resp[offset + 0] = 0;
03560
03561 return 0;
03562 }
03563
03572 static int Q921TeiSendDenyResponse(L2TRUNK trunk, L2UCHAR tei, L2USHORT ri)
03573 {
03574 if (!Q921_IS_PTMP_NT(trunk))
03575 return 0;
03576
03577 return Q921TeiSend(trunk, Q921_TEI_ID_DENIED, ri, tei);
03578 }
03579
03580
03591 static int Q921TeiSendAssignedResponse(L2TRUNK trunk, L2UCHAR tei, L2USHORT ri)
03592 {
03593 if (!Q921_IS_PTMP_NT(trunk))
03594 return 0;
03595
03596 return Q921TeiSend(trunk, Q921_TEI_ID_ASSIGNED, ri, tei);
03597 }
03598
03608 static int Q921TeiSendRemoveRequest(L2TRUNK trunk, L2UCHAR tei)
03609 {
03610 if (!Q921_IS_PTMP_NT(trunk))
03611 return 0;
03612
03613 return Q921TeiSend(trunk, Q921_TEI_ID_REMOVE, 0, tei);
03614 }
03615
03616
03617 #ifdef Q921_STATISTICS
03618
03621 static struct Q921StatsCounter
03622 {
03623 const int id;
03624 const char *name;
03625 const char *desc;
03626 } Q921StatsCounters[] = {
03627
03628 { Q921_STATS_ST01, "ST01", "State: TEI Unassigned" },
03629 { Q921_STATS_ST02, "ST02", "State: TEI Awaiting" },
03630 { Q921_STATS_ST03, "ST03", "State: TEI Establish" },
03631 { Q921_STATS_ST04, "ST04", "State: TEI Assigned" },
03632 { Q921_STATS_ST05, "ST05", "State: Awaiting Establishment" },
03633 { Q921_STATS_ST06, "ST06", "State: Awaiting Release" },
03634 { Q921_STATS_ST07, "ST07", "State: Multiple Frame Established" },
03635 { Q921_STATS_ST08, "ST08", "State: Timer Recovery" },
03636
03637
03638 { Q921_STATS_T200, "T200", "Timer: T200 Timeouts" },
03639 { Q921_STATS_T201, "T201", "Timer: T201 Timeouts" },
03640 { Q921_STATS_T202, "T202", "Timer: T202 Timeouts" },
03641 { Q921_STATS_T203, "T203", "Timer: T203 Timeouts" },
03642
03643 { Q921_STATS_TM01, "TM01", "Timer: TM01 Timeouts" },
03644
03645 { Q921_STATS_N200, "N200", "" },
03646 { Q921_STATS_N201, "N201", "" },
03647 { Q921_STATS_N202, "N202", "" },
03648
03649 #ifdef Q921_STATISTICS_VERBOSE
03650
03651 { Q921_STATS_SEND_S, "S", "TX: S frame" },
03652 { Q921_STATS_SEND_U, "U", "TX: U frame" },
03653 { Q921_STATS_SEND_I, "I", "TX: I frame" },
03654
03655 { Q921_STATS_SEND_RR, "RR", "TX: Receiver-Ready" },
03656 { Q921_STATS_SEND_RNR, "RNR", "TX: Receiver-Not-Ready" },
03657 { Q921_STATS_SEND_REJ, "REJ", "TX: Reject" },
03658 { Q921_STATS_SEND_SABME, "SABME", "TX: SABME" },
03659 { Q921_STATS_SEND_DM, "DM", "TX: Disconnected-Mode" },
03660 { Q921_STATS_SEND_DISC, "DISC", "TX: Disconnect" },
03661 { Q921_STATS_SEND_UA, "UA", "TX: UA" },
03662 { Q921_STATS_SEND_UN, "UN", "TX: UN" },
03663
03664
03665 { Q921_STATS_RECV_S, "S", "RX: S frame" },
03666 { Q921_STATS_RECV_U, "U", "RX: U frame" },
03667 { Q921_STATS_RECV_I, "I", "RX: I frame" },
03668
03669 { Q921_STATS_RECV_INVALID_S, "Invalid S", "RX: Invalid S frame" },
03670 { Q921_STATS_RECV_INVALID_U, "Invalid U", "RX: Invalid U frame" },
03671 { Q921_STATS_RECV_INVALID_I, "Invalid I", "RX: Invalid I frame" },
03672
03673 { Q921_STATS_RECV_SABME, "SABME", "RX: SABME" },
03674 { Q921_STATS_RECV_DM, "DM", "RX: Disconnected-Mode" },
03675 { Q921_STATS_RECV_UA, "UA", "RX: UA" },
03676 { Q921_STATS_RECV_DISC, "DISC", "RX: Disconnect" },
03677 { Q921_STATS_RECV_RR, "RR", "RX: Receiver-Ready" },
03678 { Q921_STATS_RECV_REJ, "REJ", "RX: Reject" },
03679 { Q921_STATS_RECV_RNR, "RNR", "RX: Receiver-Not-Ready" },
03680 #endif
03681
03682
03683 { 0, NULL, NULL }
03684 };
03685
03686 int Q921StatsCounterIsGlobal(const int id)
03687 {
03688 switch (id) {
03689 case Q921_STATS_T202:
03690 case Q921_STATS_N201:
03691 return 1;
03692 default:
03693 return 0;
03694 }
03695 }
03696
03697 const char *Q921StatsCounterGetDescription(const int id)
03698 {
03699 struct Q921StatsCounter *info = Q921StatsCounters;
03700
03701 if (id <= Q921_STATS_NONE || id >= Q921_STATS_MAX)
03702 return "invalid";
03703
03704 while (info->id) {
03705 if (info->id == id)
03706 return info->desc;
03707 info++;
03708 }
03709 return "";
03710 }
03711
03712 const char *Q921StatsCounterGetName(const int id)
03713 {
03714 struct Q921StatsCounter *info = Q921StatsCounters;
03715
03716 if (id <= Q921_STATS_NONE || id >= Q921_STATS_MAX)
03717 return "invalid";
03718
03719 while (info->id) {
03720 if (info->id == id)
03721 return info->name;
03722 info++;
03723 }
03724 return "";
03725 }
03726
03737 unsigned int Q921StatsGetCounter(const L2TRUNK trunk, const int id, const int tei)
03738 {
03739 struct Q921_Link *link = NULL;
03740
03741 if (!trunk)
03742 return 0;
03743
03744 if (id <= Q921_STATS_NONE || id >= Q921_STATS_MAX)
03745 return 0;
03746
03747 if (Q921StatsCounterIsGlobal(id)) {
03748 link = Q921_TRUNK_CONTEXT(trunk);
03749
03750 } else if (tei == Q921_TEI_BCAST) {
03751 unsigned int sum = 0;
03752 int i;
03753
03754 link = Q921_TRUNK_CONTEXT(trunk);
03755
03756 sum += link->stats.counter[id];
03757
03758 if (Q921_IS_PTMP(trunk)) {
03759 for (i = 1; i < Q921_TEI_BCAST; i++) {
03760 link = Q921_LINK_CONTEXT(trunk, i);
03761
03762 sum += link->stats.counter[id];
03763 }
03764 }
03765
03766 return sum;
03767 } else {
03768 link = Q921_LINK_CONTEXT(trunk, tei);
03769 }
03770
03771 return link->stats.counter[id];
03772 }
03773
03781 void Q921StatsResetCounters(L2TRUNK trunk)
03782 {
03783 int x, nlinks;
03784
03785 if (!trunk)
03786 return;
03787
03788 nlinks = Q921_IS_PTMP(trunk) ? Q921_TEI_MAX : 1;
03789
03790
03791 for (x = 0; x < nlinks; x++) {
03792 memset(&trunk->context[x].stats, 0, sizeof(Q921Stats_t));
03793 }
03794 }
03795
03796 static void Q921StatsIncrementCounter(struct Q921_Link *link, const int id)
03797 {
03798 if (!link)
03799 return;
03800
03801 if (id <= Q921_STATS_NONE || id >= Q921_STATS_MAX)
03802 return;
03803
03804 link->stats.counter[id]++;
03805 }
03806
03807
03808 int Q921StatsReport(const L2TRUNK trunk, const int tei)
03809 {
03810 struct Q921StatsCounter *info = Q921StatsCounters;
03811 char buf[Q921_LOGBUFSIZE];
03812 size_t len = Q921_LOGBUFSIZE - 1;
03813 size_t left = len;
03814 size_t offset = 0;
03815
03816 memset(buf, 0, sizeof(buf));
03817
03818 APPEND_MSG(buf, offset, left, "\n================== TEI: %3d ===============\n", tei)
03819
03820 while (info->id) {
03821 APPEND_MSG(buf, offset, left, "%-10s:\t%6d\t[%s]\n",
03822 info->name,
03823 Q921StatsGetCounter(trunk, info->id, tei),
03824 info->desc ? info->desc : "");
03825 info++;
03826 }
03827
03828 APPEND_MSG(buf, offset, left, "===========================================\n")
03829 out:
03830 buf[sizeof(buf) - 1] = '\0';
03831
03832 return trunk->Q921LogProc(trunk->PrivateDataLog, Q921_LOG_INFO, buf, strlen(buf));
03833 }
03834 #endif