[libpri-commits] rmudgett: branch 1.4 r1923 - /branches/1.4/q921.c
SVN commits to the libpri project
libpri-commits at lists.digium.com
Mon Aug 30 14:31:48 CDT 2010
Author: rmudgett
Date: Mon Aug 30 14:31:46 2010
New Revision: 1923
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1923
Log:
Q.921 improvements from comparing Q.921 SDL diagrams with implementation.
* Handle sending and receiving DM response frames as needed.
* Added handling of received FRMR frames.
* Completed implementation of Q921_AWAITING_RELEASE state. (State is
currently unreachable since we have no API to initiate sending the DISC
message.)
* Better NT PTMP TEI allocation.
* Reduced more ERROR level severity messages so users will stop panicking
when they see ERROR. This is especially true for the Q.921 MDL-ERROR
messages.
* Added better Q.921 visibility when normal debug message level is enabled.
Modified:
branches/1.4/q921.c
Modified: branches/1.4/q921.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/q921.c?view=diff&rev=1923&r1=1922&r2=1923
==============================================================================
--- branches/1.4/q921.c (original)
+++ branches/1.4/q921.c Mon Aug 30 14:31:46 2010
@@ -43,10 +43,7 @@
* Define RANDOM_DROPS To randomly drop packets in order to simulate loss for testing
* retransmission functionality
*/
-
-/*
-#define RANDOM_DROPS
-*/
+//#define RANDOM_DROPS 1
#define Q921_INIT(ctrl, hf) do { \
memset(&(hf),0,sizeof(hf)); \
@@ -130,22 +127,18 @@
ctrl->q921_state = newstate;
}
-static void q921_discard_retransmissions(struct pri *ctrl)
+static void q921_discard_iqueue(struct pri *ctrl)
{
struct q921_frame *f, *p;
+
f = ctrl->txqueue;
- while(f) {
+ while (f) {
p = f;
f = f->next;
/* Free frame */
free(p);
}
ctrl->txqueue = NULL;
-}
-
-static void q921_discard_iqueue(struct pri *ctrl)
-{
- q921_discard_retransmissions(ctrl);
}
static int q921_transmit(struct pri *ctrl, q921_h *h, int len)
@@ -190,8 +183,9 @@
f->data[2] = ri & 0xff;
f->data[3] = message;
f->data[4] = (ai << 1) | 1;
- if (ctrl->debug & PRI_DEBUG_Q921_STATE)
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
pri_message(ctrl, "Sending TEI management message %d, TEI=%d\n", message, ai);
+ }
q921_transmit(ctrl, (q921_h *)f, 8);
free(f);
}
@@ -241,13 +235,65 @@
t202_expire(ctrl);
}
-static void q921_send_ua(struct pri *ctrl, int pfbit)
+static void q921_send_dm(struct pri *ctrl, int fbit)
+{
+ q921_h h;
+
+ Q921_INIT(ctrl, h);
+ h.u.m3 = 0; /* M3 = 0 */
+ h.u.m2 = 3; /* M2 = 3 */
+ h.u.p_f = fbit; /* Final set appropriately */
+ h.u.ft = Q921_FRAMETYPE_U;
+ switch(ctrl->localtype) {
+ case PRI_NETWORK:
+ h.h.c_r = 0;
+ break;
+ case PRI_CPE:
+ h.h.c_r = 1;
+ break;
+ default:
+ pri_error(ctrl, "Don't know how to DM on a type %d node\n", ctrl->localtype);
+ return;
+ }
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Sending DM\n", ctrl->tei);
+ }
+ q921_transmit(ctrl, &h, 4);
+}
+
+static void q921_send_disc(struct pri *ctrl, int pbit)
+{
+ q921_h h;
+
+ Q921_INIT(ctrl, h);
+ h.u.m3 = 2; /* M3 = 2 */
+ h.u.m2 = 0; /* M2 = 0 */
+ h.u.p_f = pbit; /* Poll set appropriately */
+ h.u.ft = Q921_FRAMETYPE_U;
+ switch(ctrl->localtype) {
+ case PRI_NETWORK:
+ h.h.c_r = 0;
+ break;
+ case PRI_CPE:
+ h.h.c_r = 1;
+ break;
+ default:
+ pri_error(ctrl, "Don't know how to DISC on a type %d node\n", ctrl->localtype);
+ return;
+ }
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Sending DISC\n", ctrl->tei);
+ }
+ q921_transmit(ctrl, &h, 4);
+}
+
+static void q921_send_ua(struct pri *ctrl, int fbit)
{
q921_h h;
Q921_INIT(ctrl, h);
h.u.m3 = 3; /* M3 = 3 */
h.u.m2 = 0; /* M2 = 0 */
- h.u.p_f = pfbit; /* Final bit on */
+ h.u.p_f = fbit; /* Final set appropriately */
h.u.ft = Q921_FRAMETYPE_U;
switch(ctrl->localtype) {
case PRI_NETWORK:
@@ -257,11 +303,12 @@
h.h.c_r = 1;
break;
default:
- pri_error(ctrl, "Don't know how to U/A on a type %d node\n", ctrl->localtype);
+ pri_error(ctrl, "Don't know how to UA on a type %d node\n", ctrl->localtype);
return;
}
- if (ctrl->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))
- pri_message(ctrl, "Sending Unnumbered Acknowledgement\n");
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Sending UA\n", ctrl->tei);
+ }
q921_transmit(ctrl, &h, 3);
}
@@ -282,8 +329,11 @@
h.h.c_r = 0;
break;
default:
- pri_error(ctrl, "Don't know how to U/A on a type %d node\n", ctrl->localtype);
+ pri_error(ctrl, "Don't know how to SABME on a type %d node\n", ctrl->localtype);
return;
+ }
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Sending SABME\n", ctrl->tei);
}
q921_transmit(ctrl, &h, 3);
}
@@ -297,9 +347,13 @@
static int q921_ack_packet(struct pri *ctrl, int num)
{
- struct q921_frame *f, *prev = NULL;
- f = ctrl->txqueue;
- while (f) {
+ struct q921_frame *f;
+ struct q921_frame *prev;
+
+ for (prev = NULL, f = ctrl->txqueue; f; prev = f, f = f->next) {
+ if (!f->transmitted) {
+ break;
+ }
if (f->h.n_s == num) {
/* Cancel each packet as necessary */
/* That's our packet */
@@ -307,14 +361,20 @@
prev->next = f->next;
else
ctrl->txqueue = f->next;
- if (ctrl->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(ctrl, "-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, ctrl->txqueue ? ctrl->txqueue->h.n_s : -1);
+ if (ctrl->debug & PRI_DEBUG_Q921_DUMP) {
+ pri_message(ctrl,
+ "-- ACKing N(S)=%d, txqueue head is N(S)=%d (-1 is empty, -2 is not transmitted)\n",
+ f->h.n_s,
+ ctrl->txqueue
+ ? ctrl->txqueue->transmitted
+ ? ctrl->txqueue->h.n_s
+ : -2
+ : -1);
+ }
/* Update v_a */
free(f);
return 1;
}
- prev = f;
- f = f->next;
}
return 0;
}
@@ -414,40 +474,61 @@
struct q921_frame *f;
int frames_txd = 0;
- if (ctrl->peer_rx_busy || (ctrl->v_s == Q921_ADD(ctrl->v_a, ctrl->timers[PRI_TIMER_K]))) {
- if (ctrl->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(ctrl, "Couldn't transmit I-frame at this time due to peer busy condition or window shut\n");
+ for (f = ctrl->txqueue; f; f = f->next) {
+ if (!f->transmitted) {
+ /* This frame has not been sent yet. */
+ break;
+ }
+ }
+ if (!f) {
+ /* The Tx queue has no pending frames. */
return 0;
}
- f = ctrl->txqueue;
- while (f && (ctrl->v_s != Q921_ADD(ctrl->v_a, ctrl->timers[PRI_TIMER_K]))) {
- if (!f->transmitted) {
- /* Send it now... */
- if (ctrl->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(ctrl, "-- Finally transmitting %d, since window opened up (%d)\n", f->h.n_s, ctrl->timers[PRI_TIMER_K]);
- f->transmitted++;
-
- /*
- * Send the frame out on the assigned TEI.
- * Done now because the frame may have been queued before we
- * had an assigned TEI.
- */
- f->h.h.tei = ctrl->tei;
-
- f->h.n_s = ctrl->v_s;
- f->h.n_r = ctrl->v_r;
- f->h.ft = 0;
- f->h.p_f = 0;
- q921_transmit(ctrl, (q921_h *)(&f->h), f->len);
- Q921_INC(ctrl->v_s);
- frames_txd++;
- ctrl->acknowledge_pending = 0;
- }
- f = f->next;
+ if (ctrl->peer_rx_busy
+ || (ctrl->v_s == Q921_ADD(ctrl->v_a, ctrl->timers[PRI_TIMER_K]))) {
+ /* Don't flood debug trace if not really looking at Q.921 layer. */
+ if (ctrl->debug & (/* PRI_DEBUG_Q921_STATE | */ PRI_DEBUG_Q921_DUMP)) {
+ pri_message(ctrl,
+ "TEI=%d Couldn't transmit I-frame at this time due to peer busy condition or window shut\n",
+ ctrl->tei);
+ }
+ return 0;
+ }
+
+ /* Send all pending frames that fit in the window. */
+ for (; f; f = f->next) {
+ if (ctrl->v_s == Q921_ADD(ctrl->v_a, ctrl->timers[PRI_TIMER_K])) {
+ /* The window is no longer open. */
+ break;
+ }
+
+ /* Send it now... */
+ ++f->transmitted;
+
+ /*
+ * Send the frame out on the assigned TEI.
+ * Done now because the frame may have been queued before we
+ * had an assigned TEI.
+ */
+ f->h.h.tei = ctrl->tei;
+
+ f->h.n_s = ctrl->v_s;
+ f->h.n_r = ctrl->v_r;
+ f->h.ft = 0;
+ f->h.p_f = 0;
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl,
+ "TEI=%d Transmitting N(S)=%d, window is open V(A)=%d K=%d\n",
+ ctrl->tei, f->h.n_s, ctrl->v_a, ctrl->timers[PRI_TIMER_K]);
+ }
+ q921_transmit(ctrl, (q921_h *)(&f->h), f->len);
+ Q921_INC(ctrl->v_s);
+ ++frames_txd;
}
if (frames_txd) {
+ ctrl->acknowledge_pending = 0;
if (!ctrl->t200_timer) {
stop_t203(ctrl);
start_t200(ctrl);
@@ -460,6 +541,7 @@
static void q921_reject(struct pri *ctrl, int pf)
{
q921_h h;
+
Q921_INIT(ctrl, h);
h.s.x0 = 0; /* Always 0 */
h.s.ss = 2; /* Reject */
@@ -474,16 +556,19 @@
h.h.c_r = 1;
break;
default:
- pri_error(ctrl, "Don't know how to U/A on a type %d node\n", ctrl->localtype);
+ pri_error(ctrl, "Don't know how to REJ on a type %d node\n", ctrl->localtype);
return;
}
- if (ctrl->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(ctrl, "Sending Reject (%d)\n", ctrl->v_r);
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Sending REJ N(R)=%d\n", ctrl->tei, ctrl->v_r);
+ }
q921_transmit(ctrl, &h, 4);
}
-static void q921_rr(struct pri *ctrl, int pbit, int cmd) {
+static void q921_rr(struct pri *ctrl, int pbit, int cmd)
+{
q921_h h;
+
Q921_INIT(ctrl, h);
h.s.x0 = 0; /* Always 0 */
h.s.ss = 0; /* Receive Ready */
@@ -504,11 +589,14 @@
h.h.c_r = 1;
break;
default:
- pri_error(ctrl, "Don't know how to U/A on a type %d node\n", ctrl->localtype);
+ pri_error(ctrl, "Don't know how to RR on a type %d node\n", ctrl->localtype);
return;
}
- if (ctrl->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(ctrl, "Sending Receiver Ready (%d)\n", ctrl->v_r);
+#if 0 /* Don't flood debug trace with RR if not really looking at Q.921 layer. */
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Sending RR N(R)=%d\n", ctrl->tei, ctrl->v_r);
+ }
+#endif
q921_transmit(ctrl, &h, 4);
}
@@ -577,8 +665,22 @@
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
}
break;
+ case Q921_AWAITING_RELEASE:
+ if (ctrl->RC != ctrl->timers[PRI_TIMER_N200]) {
+ ++ctrl->RC;
+ q921_send_disc(ctrl, 1);
+ start_t200(ctrl);
+ } else {
+ //pri_error(ctrl, "MDL-ERROR (H) : T200 expired N200 times in state %d(%s)\n",
+ // ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ q921_mdl_error(ctrl, 'H');
+ /* DL-RELEASE confirm */
+ q921_setstate(ctrl, Q921_TEI_ASSIGNED);
+ }
+ break;
default:
- pri_error(ctrl, "Cannot handle T200 expire in state %d(%s)\n",
+ /* Looks like someone forgot to stop the T200 timer. */
+ pri_error(ctrl, "T200 expired in state %d(%s)\n",
ctrl->q921_state, q921_state2str(ctrl->q921_state));
break;
}
@@ -614,7 +716,7 @@
h->h.c_r = 0;
break;
default:
- pri_error(ctrl, "Don't know how to U/A on a type %d node\n", ctrl->localtype);
+ pri_error(ctrl, "Don't know how to UI-frame on a type %d node\n", ctrl->localtype);
return -1;
}
@@ -719,17 +821,20 @@
ctrl->txqueue = f;
if (ctrl->q921_state != Q921_MULTI_FRAME_ESTABLISHED) {
- if (ctrl->debug & PRI_DEBUG_Q921_DUMP) {
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
pri_message(ctrl,
- "Just queued I-frame since not in state %d(%s)\n",
- Q921_MULTI_FRAME_ESTABLISHED, q921_state2str(Q921_MULTI_FRAME_ESTABLISHED));
+ "TEI=%d Just queued I-frame since in state %d(%s)\n",
+ ctrl->tei,
+ ctrl->q921_state, q921_state2str(ctrl->q921_state));
}
return 0;
}
if (ctrl->peer_rx_busy || (ctrl->v_s == Q921_ADD(ctrl->v_a, ctrl->timers[PRI_TIMER_K]))) {
- if (ctrl->debug & PRI_DEBUG_Q921_DUMP) {
- pri_message(ctrl, "Just queued I-frame due to peer busy condition or window shut\n");
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl,
+ "TEI=%d Just queued I-frame due to peer busy condition or window shut\n",
+ ctrl->tei);
}
return 0;
}
@@ -755,9 +860,12 @@
static void t203_expire(void *vpri)
{
struct pri *ctrl = vpri;
+
if (ctrl->debug & PRI_DEBUG_Q921_DUMP)
pri_message(ctrl, "%s\n", __FUNCTION__);
+
ctrl->t203_timer = 0;
+
switch (ctrl->q921_state) {
case Q921_MULTI_FRAME_ESTABLISHED:
transmit_enquiry(ctrl);
@@ -765,22 +873,21 @@
q921_setstate(ctrl, Q921_TIMER_RECOVERY);
break;
default:
- if (ctrl->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(ctrl, "T203 counter expired in weird state %d(%s)\n",
- ctrl->q921_state, q921_state2str(ctrl->q921_state));
- ctrl->t203_timer = 0;
- break;
- }
-}
-
-static void q921_dump_iqueue_info(struct pri *ctrl, int force)
+ /* Looks like someone forgot to stop the T203 timer. */
+ pri_error(ctrl, "T203 expired in state %d(%s)\n",
+ ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ break;
+ }
+}
+
+static void q921_dump_iqueue_info(struct pri *ctrl)
{
struct q921_frame *f;
int pending = 0, unacked = 0;
unacked = pending = 0;
- for (f = ctrl->txqueue; f && f->next; f = f->next) {
+ for (f = ctrl->txqueue; f; f = f->next) {
if (f->transmitted) {
unacked++;
} else {
@@ -788,10 +895,7 @@
}
}
- if (force)
- pri_error(ctrl, "Number of pending packets %d, sent but unacked %d\n", pending, unacked);
-
- return;
+ pri_error(ctrl, "Number of pending packets %d, sent but unacked %d\n", pending, unacked);
}
static void q921_dump_pri_by_h(struct pri *ctrl, char direction_tag, q921_h *h);
@@ -972,8 +1076,8 @@
{
pri_message(ctrl, "%c TEI: %d State %d(%s)\n",
direction_tag, ctrl->tei, ctrl->q921_state, q921_state2str(ctrl->q921_state));
- pri_message(ctrl, "%c V(S)=%d, V(A)=%d, V(R)=%d\n",
- direction_tag, ctrl->v_s, ctrl->v_a, ctrl->v_r);
+ pri_message(ctrl, "%c V(A)=%d, V(S)=%d, V(R)=%d\n",
+ direction_tag, ctrl->v_a, ctrl->v_s, ctrl->v_r);
pri_message(ctrl, "%c K=%d, RC=%d, l3initiated=%d, reject_except=%d, ack_pend=%d\n",
direction_tag, ctrl->timers[PRI_TIMER_K], ctrl->RC, ctrl->l3initiated,
ctrl->reject_exception, ctrl->acknowledge_pending);
@@ -1004,17 +1108,18 @@
static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
{
int ri;
- struct pri *sub = ctrl;
+ struct pri *sub;
pri_event *res = NULL;
int tei;
if (!BRI_NT_PTMP(ctrl) && !BRI_TE_PTMP(ctrl)) {
- pri_error(ctrl, "Received MDL/TEI managemement message, but configured for mode other than PTMP!\n");
- return NULL;
- }
-
- if (ctrl->debug & PRI_DEBUG_Q921_STATE)
+ return pri_mkerror(ctrl,
+ "Received MDL/TEI managemement message, but configured for mode other than PTMP!\n");
+ }
+
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
pri_message(ctrl, "Received MDL message\n");
+ }
if (h->data[0] != 0x0f) {
pri_error(ctrl, "Received MDL with unsupported management entity %02x\n", h->data[0]);
return NULL;
@@ -1032,31 +1137,38 @@
return NULL;
}
- if (tei != 127) {
+ if (tei != Q921_TEI_GROUP) {
pri_error(ctrl, "Received TEI identity request with invalid TEI %d\n", tei);
q921_send_tei(ctrl, Q921_TEI_IDENTITY_DENIED, ri, tei, 1);
- }
+ return NULL;
+ }
+
+ /* Find a TEI that is not allocated. */
tei = 64;
- while (sub->subchannel) {
- if (sub->subchannel->tei == tei)
- ++tei;
- sub = sub->subchannel;
- }
-
- if (tei >= Q921_TEI_GROUP) {
- pri_error(ctrl, "Reached maximum TEI quota, cannot assign new TEI\n");
- return NULL;
+ do {
+ for (sub = ctrl; sub->subchannel; sub = sub->subchannel) {
+ if (sub->subchannel->tei == tei) {
+ /* This TEI is already assigned, try next one. */
+ ++tei;
+ if (tei < Q921_TEI_GROUP) {
+ break;
+ }
+ /* XXX : TODO later sometime: Implement the TEI check procedure to reclaim some dead TEIs. */
+ pri_error(ctrl, "Reached maximum TEI quota, cannot assign new TEI\n");
+ return NULL;
+ }
+ }
+ } while (sub->subchannel);
+
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "Allocating new TEI %d\n", tei);
}
sub->subchannel = __pri_new_tei(-1, ctrl->localtype, ctrl->switchtype, ctrl, NULL, NULL, NULL, tei, 1);
-
if (!sub->subchannel) {
pri_error(ctrl, "Unable to allocate D-channel for new TEI %d\n", tei);
return NULL;
}
q921_setstate(sub->subchannel, Q921_TEI_ASSIGNED);
- if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
- pri_message(ctrl, "Allocating new TEI %d\n", tei);
- }
q921_send_tei(ctrl, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 1);
break;
case Q921_TEI_IDENTITY_ASSIGNED:
@@ -1082,7 +1194,11 @@
pri_schedule_del(ctrl, ctrl->t202_timer);
ctrl->t202_timer = 0;
+
ctrl->tei = tei;
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "Got assigned TEI %d\n", tei);
+ }
switch (ctrl->q921_state) {
case Q921_ASSIGN_AWAITING_TEI:
@@ -1098,22 +1214,22 @@
res = &ctrl->ev;
break;
default:
- pri_error(ctrl, "Error 3\n");
- return NULL;
- }
-
+ break;
+ }
break;
case Q921_TEI_IDENTITY_CHECK_REQUEST:
if (!BRI_TE_PTMP(ctrl))
return NULL;
- if (ctrl->subchannel->q921_state < Q921_TEI_ASSIGNED)
+ if (ctrl->subchannel->q921_state < Q921_TEI_ASSIGNED) {
+ /* We do not have a TEI. */
return NULL;
+ }
/* If it's addressed to the group TEI or to our TEI specifically, we respond */
- if ((tei == Q921_TEI_GROUP) || (tei == ctrl->subchannel->tei))
+ if ((tei == Q921_TEI_GROUP) || (tei == ctrl->subchannel->tei)) {
q921_send_tei(ctrl, Q921_TEI_IDENTITY_CHECK_RESPONSE, random() % 65535, ctrl->subchannel->tei, 1);
-
+ }
break;
case Q921_TEI_IDENTITY_REMOVE:
if (!BRI_TE_PTMP(ctrl))
@@ -1195,6 +1311,8 @@
q921_send_ua(ctrl, h->u.p_f);
break;
case Q921_AWAITING_RELEASE:
+ q921_send_dm(ctrl, h->u.p_f);
+ break;
default:
pri_error(ctrl, "Cannot handle SABME in state %d(%s)\n",
ctrl->q921_state, q921_state2str(ctrl->q921_state));
@@ -1208,7 +1326,15 @@
{
pri_event * res = NULL;
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Got DISC\n", ctrl->tei);
+ }
+
switch (ctrl->q921_state) {
+ case Q921_TEI_ASSIGNED:
+ case Q921_AWAITING_ESTABLISHMENT:
+ q921_send_dm(ctrl, h->u.p_f);
+ break;
case Q921_AWAITING_RELEASE:
q921_send_ua(ctrl, h->u.p_f);
break;
@@ -1218,7 +1344,6 @@
q921_send_ua(ctrl, h->u.p_f);
/* DL-RELEASE Indication */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
-
stop_t200(ctrl);
if (ctrl->q921_state == Q921_MULTI_FRAME_ESTABLISHED)
stop_t203(ctrl);
@@ -1238,6 +1363,9 @@
{
int mdl_free_me;
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "MDL-REMOVE: Removing TEI %d\n", ctrl->tei);
+ }
if (BRI_NT_PTMP(ctrl)) {
if (ctrl == PRI_MASTER(ctrl)) {
pri_error(ctrl, "Bad bad bad! Cannot MDL-REMOVE master\n");
@@ -1287,6 +1415,12 @@
ctrl->q921_state, q921_state2str(ctrl->q921_state));
return;
}
+
+ /*
+ * Negate the TEI value so debug messages will display a
+ * negated TEI when it is actually unassigned.
+ */
+ ctrl->tei = -ctrl->tei;
ctrl->mdl_free_me = mdl_free_me;
}
@@ -1307,6 +1441,9 @@
case 'E':
case 'F':
case 'I':
+ case 'J':
+ case 'K':
+ break;
default:
pri_error(ctrl, "Network MDL can't handle error of type %c\n", error);
break;
@@ -1332,6 +1469,8 @@
case 'E':
case 'F':
case 'I':
+ case 'J':
+ case 'K':
break;
default:
pri_error(ctrl, "CPE MDL can't handle error of type %c\n", error);
@@ -1363,6 +1502,17 @@
handled = 1;
break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ break;
default:
pri_error(ctrl, "PTP MDL can't handle error of type %c\n", error);
break;
@@ -1380,56 +1530,15 @@
static void q921_mdl_handle_error(struct pri *ctrl, char error, int errored_state)
{
- int handled = 0;
if (PTP_MODE(ctrl)) {
- handled = q921_mdl_handle_ptp_error(ctrl, error);
+ q921_mdl_handle_ptp_error(ctrl, error);
} else {
if (ctrl->localtype == PRI_NETWORK) {
- handled = q921_mdl_handle_network_error(ctrl, error);
+ q921_mdl_handle_network_error(ctrl, error);
} else {
- handled = q921_mdl_handle_cpe_error(ctrl, error);
- }
- }
-
- if (handled)
- return;
-
- switch (error) {
- case 'C':
- pri_error(ctrl, "MDL-ERROR (C): UA in state %d(%s)\n",
- errored_state, q921_state2str(errored_state));
- break;
- case 'D':
- pri_error(ctrl, "MDL-ERROR (D): UA in state %d(%s)\n",
- errored_state, q921_state2str(errored_state));
- break;
- case 'A':
- pri_error(ctrl, "MDL-ERROR (A): Got supervisory frame with p_f bit set to 1 in state %d(%s)\n",
- errored_state, q921_state2str(errored_state));
- break;
- case 'I':
- pri_error(ctrl, "MDL-ERROR (I): T200 = N200 in timer recovery state %d(%s)\n",
- errored_state, q921_state2str(errored_state));
- break;
- case 'G':
- pri_error(ctrl, "MDL-ERROR (G) : T200 expired N200 times in state %d(%s)\n",
- errored_state, q921_state2str(errored_state));
- break;
- case 'F':
- pri_error(ctrl, "MDL-ERROR (F), SABME in state %d(%s)\n",
- errored_state, q921_state2str(errored_state));
- break;
- case 'H':
- case 'B':
- case 'E':
- case 'J':
- default:
- pri_error(ctrl, "MDL-ERROR (%c) in state %d(%s)\n", error,
- errored_state, q921_state2str(errored_state));
- break;
- }
-
- return;
+ q921_mdl_handle_cpe_error(ctrl, error);
+ }
+ }
}
static void q921_mdl_handle_error_callback(void *vpri)
@@ -1458,12 +1567,12 @@
}
if (freep == NULL) {
- pri_error(ctrl, "Huh!? no match found in list for TEI %d\n", ctrl->tei);
+ pri_error(ctrl, "Huh!? no match found in list for TEI %d\n", -ctrl->tei);
return;
}
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
- pri_message(ctrl, "Freeing TEI of %d\n", freep->tei);
+ pri_message(ctrl, "Freeing TEI of %d\n", -freep->tei);
}
__pri_free_tei(freep);
@@ -1474,8 +1583,97 @@
static void q921_mdl_error(struct pri *ctrl, char error)
{
+ int is_debug_q921_state;
+
+ /* Log the MDL-ERROR event when detected. */
+ is_debug_q921_state = (ctrl->debug & PRI_DEBUG_Q921_STATE);
+ switch (error) {
+ case 'A':
+ pri_message(ctrl,
+ "TEI=%d MDL-ERROR (A): Got supervisory frame with F=1 in state %d(%s)\n",
+ ctrl->tei, ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ break;
+ case 'B':
+ case 'E':
+ pri_message(ctrl, "TEI=%d MDL-ERROR (%c): DM (F=%c) in state %d(%s)\n",
+ ctrl->tei, error, (error == 'B') ? '1' : '0',
+ ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ break;
+ case 'C':
+ case 'D':
+ if (is_debug_q921_state || PTP_MODE(ctrl)) {
+ pri_message(ctrl, "TEI=%d MDL-ERROR (%c): UA (F=%c) in state %d(%s)\n",
+ ctrl->tei, error, (error == 'C') ? '1' : '0',
+ ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ }
+ break;
+ case 'F':
+ /*
+ * The peer is restarting the link.
+ * Some reasons this might happen:
+ * 1) Our link establishment requests collided.
+ * 2) They got reset.
+ * 3) They could not talk to us for some reason because
+ * their T200 timer expired N200 times.
+ * 4) They got an MDL-ERROR (J).
+ */
+ if (is_debug_q921_state) {
+ /*
+ * This message is rather annoying and is normal for
+ * reasons 1-3 above.
+ */
+ pri_message(ctrl, "TEI=%d MDL-ERROR (F): SABME in state %d(%s)\n",
+ ctrl->tei, ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ }
+ break;
+ case 'G':
+ /* We could not get a response from the peer. */
+ if (is_debug_q921_state) {
+ pri_message(ctrl,
+ "TEI=%d MDL-ERROR (G): T200 expired N200 times sending SABME in state %d(%s)\n",
+ ctrl->tei, ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ }
+ break;
+ case 'H':
+ /* We could not get a response from the peer. */
+ if (is_debug_q921_state) {
+ pri_message(ctrl,
+ "TEI=%d MDL-ERROR (H): T200 expired N200 times sending DISC in state %d(%s)\n",
+ ctrl->tei, ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ }
+ break;
+ case 'I':
+ /* We could not get a response from the peer. */
+ if (is_debug_q921_state) {
+ pri_message(ctrl,
+ "TEI=%d MDL-ERROR (I): T200 expired N200 times sending RR/RNR in state %d(%s)\n",
+ ctrl->tei, ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ }
+ break;
+ case 'J':
+ /* N(R) not within ack window. */
+ pri_error(ctrl, "TEI=%d MDL-ERROR (J): N(R) error in state %d(%s)\n",
+ ctrl->tei, ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ break;
+ case 'K':
+ /*
+ * Received a frame reject frame.
+ * The other end does not like what we are doing at all for some reason.
+ */
+ pri_error(ctrl, "TEI=%d MDL-ERROR (K): FRMR in state %d(%s)\n",
+ ctrl->tei, ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ break;
+ default:
+ pri_message(ctrl, "TEI=%d MDL-ERROR (%c): in state %d(%s)\n",
+ ctrl->tei, error, ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ break;
+ }
+
if (ctrl->mdl_error) {
- pri_error(ctrl, "Trying to queue an MDL error when one is already scheduled\n");
+ /* This should not happen. */
+ pri_error(ctrl,
+ "Trying to queue MDL-ERROR (%c) when MDL-ERROR (%c) is already scheduled\n",
+ error, ctrl->mdl_error);
return;
}
ctrl->mdl_error = error;
@@ -1487,18 +1685,29 @@
{
pri_event * res = NULL;
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Got UA\n", ctrl->tei);
+ }
+
switch (ctrl->q921_state) {
case Q921_TEI_ASSIGNED:
- //pri_error(ctrl, "MDL-ERROR (C, D): UA received in state %d(%s)\n",
- // ctrl->q921_state, q921_state2str(ctrl->q921_state));
- if (h->u.p_f)
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ case Q921_TIMER_RECOVERY:
+ if (h->u.p_f) {
+ //pri_error(ctrl, "MDL-ERROR (C): UA in state %d(%s) w with P_F bit 1\n",
+ // ctrl->q921_state, q921_state2str(ctrl->q921_state));
q921_mdl_error(ctrl, 'C');
- else
+ } else {
+ //pri_error(ctrl, "MDL-ERROR (D): UA in state %d(%s) w with P_F bit 0\n",
+ // ctrl->q921_state, q921_state2str(ctrl->q921_state));
q921_mdl_error(ctrl, 'D');
+ }
break;
case Q921_AWAITING_ESTABLISHMENT:
if (!h->u.p_f) {
- pri_error(ctrl, "MDL-ERROR: Received UA with F = 0 while awaiting establishment\n");
+ //pri_error(ctrl, "MDL-ERROR (D): UA in state %d(%s) w with P_F bit 0\n",
+ // ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ q921_mdl_error(ctrl, 'D');
break;
}
@@ -1509,7 +1718,6 @@
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_UP);
}
} else {
- /* Might not want this... */
ctrl->l3initiated = 0;
/* return DL-ESTABLISH-CONFIRM */
}
@@ -1537,12 +1745,6 @@
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
}
break;
- case Q921_MULTI_FRAME_ESTABLISHED:
- case Q921_TIMER_RECOVERY:
- //pri_error(ctrl, "MDL-ERROR (C, D) UA in state %d(%s)\n",
- // ctrl->q921_state, q921_state2str(ctrl->q921_state));
- q921_mdl_error(ctrl, 'C');
- break;
default:
pri_error(ctrl, "Don't know what to do with UA in state %d(%s)\n",
ctrl->q921_state, q921_state2str(ctrl->q921_state));
@@ -1581,16 +1783,14 @@
/* Cancel each packet as necessary */
if (ctrl->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(ctrl, "-- ACKing all packets from %d to (but not including) %d\n", ctrl->v_a, n_r);
+ pri_message(ctrl, "-- Got ACK for N(S)=%d to (but not including) N(S)=%d\n", ctrl->v_a, n_r);
for (x = ctrl->v_a; x != n_r; Q921_INC(x)) {
idealcnt++;
realcnt += q921_ack_packet(ctrl, x);
}
if (idealcnt != realcnt) {
pri_error(ctrl, "Ideally should have ack'd %d frames, but actually ack'd %d. This is not good.\n", idealcnt, realcnt);
- q921_dump_iqueue_info(ctrl, 1);
- } else {
- q921_dump_iqueue_info(ctrl, 0);
+ q921_dump_iqueue_info(ctrl);
}
ctrl->v_a = n_r;
@@ -1600,9 +1800,11 @@
{
int x;
- for (x=ctrl->v_a; (x != ctrl->v_s) && (x != n_r); Q921_INC(x));
+ /* Is V(A) <= N(R) <= V(S) */
+ for (x = ctrl->v_a; x != n_r && x != ctrl->v_s; Q921_INC(x)) {
+ }
if (x != n_r) {
- pri_error(ctrl, "N(R) %d not within ack window! Bad Bad Bad!\n", n_r);
+ /* MDL-ERROR (J): N(R) is not within ack window. */
return 0;
} else {
return 1;
@@ -1655,6 +1857,13 @@
static pri_event *q921_rr_rx(struct pri *ctrl, q921_h *h)
{
pri_event * res = NULL;
+
+#if 0 /* Don't flood debug trace with RR if not really looking at Q.921 layer. */
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Got RR N(R)=%d\n", ctrl->tei, h->s.n_r);
+ }
+#endif
+
switch (ctrl->q921_state) {
case Q921_TIMER_RECOVERY:
res = timer_recovery_rr_rej_rx(ctrl, h);
@@ -1693,6 +1902,14 @@
}
}
break;
+ case Q921_TEI_ASSIGNED:
+ case Q921_AWAITING_ESTABLISHMENT:
+ case Q921_AWAITING_RELEASE:
+ /*
+ * Ignore this frame.
+ * We likely got reset and the other end has not realized it yet.
+ */
+ break;
default:
pri_error(ctrl, "Don't know what to do with RR in state %d(%s)\n",
ctrl->q921_state, q921_state2str(ctrl->q921_state));
@@ -1702,7 +1919,6 @@
return res;
}
-/* TODO: Look at this code more... */
static int q921_invoke_retransmission(struct pri *ctrl, int n_r)
{
int frames_txd = 0;
@@ -1710,25 +1926,24 @@
q921_frame *f;
unsigned int local_v_s = ctrl->v_s;
-
- for (f = ctrl->txqueue; f && (f->h.n_s != n_r); f = f->next);
- while (f) {
- if (f->transmitted) {
- if (ctrl->debug & PRI_DEBUG_Q921_STATE)
- pri_error(ctrl, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", n_r, f->h.n_s);
- f->h.n_r = ctrl->v_r;
- f->h.p_f = 0;
- q921_transmit(ctrl, (q921_h *)(&f->h), f->len);
- frames_txd++;
- }
- f = f->next;
+ /* All acked frames should already have been removed from the queue. */
+ for (f = ctrl->txqueue; f && f->transmitted; f = f->next) {
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Retransmitting frame N(S)=%d now!\n",
+ ctrl->tei, f->h.n_s);
+ }
+
+ /* Give the other side our current N(R) */
+ f->h.n_r = ctrl->v_r;
+ f->h.p_f = 0;
+ q921_transmit(ctrl, (q921_h *)(&f->h), f->len);
+ frames_txd++;
}
while (local_v_s != n_r) {
Q921_DEC(local_v_s);
frames_supposed_to_tx++;
}
-
if (frames_supposed_to_tx != frames_txd) {
pri_error(ctrl, "!!!!!!!!!!!! Should have only transmitted %d frames!\n", frames_supposed_to_tx);
}
@@ -1741,8 +1956,7 @@
pri_event * res = NULL;
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
- pri_message(ctrl, "!! Got reject for frame %d in state %d(%s)\n", h->s.n_r,
- ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ pri_message(ctrl, "TEI=%d Got REJ N(R)=%d\n", ctrl->tei, h->s.n_r);
}
switch (ctrl->q921_state) {
@@ -1775,11 +1989,55 @@
start_t203(ctrl);
q921_invoke_retransmission(ctrl, h->s.n_r);
}
- return NULL;
+ break;
+ case Q921_TEI_ASSIGNED:
+ case Q921_AWAITING_ESTABLISHMENT:
+ case Q921_AWAITING_RELEASE:
+ /*
+ * Ignore this frame.
+ * We likely got reset and the other end has not realized it yet.
+ */
+ break;
default:
- pri_error(ctrl, "Don't know what to do with RR in state %d(%s)\n",
+ pri_error(ctrl, "Don't know what to do with REJ in state %d(%s)\n",
ctrl->q921_state, q921_state2str(ctrl->q921_state));
- return NULL;
+ break;
+ }
+
+ return res;
+}
+
+static pri_event *q921_frmr_rx(struct pri *ctrl, q921_h *h)
+{
+ pri_event *res = NULL;
+
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Got FRMR\n", ctrl->tei);
+ }
+
+ switch (ctrl->q921_state) {
+ case Q921_TIMER_RECOVERY:
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ q921_mdl_error(ctrl, 'K');
+ q921_establish_data_link(ctrl);
+ ctrl->l3initiated = 0;
+ q921_setstate(ctrl, Q921_AWAITING_ESTABLISHMENT);
+ break;
+ case Q921_TEI_ASSIGNED:
+ case Q921_AWAITING_ESTABLISHMENT:
+ case Q921_AWAITING_RELEASE:
+ /*
+ * Ignore this frame.
+ * We likely got reset and the other end has not realized it yet.
+ */
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Ignoring FRMR.\n", ctrl->tei);
+ }
+ break;
+ default:
+ pri_error(ctrl, "Don't know what to do with FRMR in state %d(%s)\n",
+ ctrl->q921_state, q921_state2str(ctrl->q921_state));
+ break;
}
return res;
@@ -1797,9 +2055,7 @@
if (ctrl->own_rx_busy) {
/* XXX: Note: There's a difference in th P/F between both states */
/* DEVIATION: Handle own rx busy */
- }
-
- if (h->i.n_s == ctrl->v_r) {
+ } else if (h->i.n_s == ctrl->v_r) {
Q921_INC(ctrl->v_r);
ctrl->reject_exception = 0;
@@ -1815,11 +2071,9 @@
ctrl->acknowledge_pending = 0;
} else {
if (!ctrl->acknowledge_pending) {
- /* XXX: Fix acknowledge_pending */
ctrl->acknowledge_pending = 1;
}
}
-
} else {
if (ctrl->reject_exception) {
if (h->i.p_f) {
@@ -1850,14 +2104,20 @@
} else {
if (h->i.n_r != ctrl->v_a) {
update_v_a(ctrl, h->i.n_r);
- stop_t200(ctrl);
- start_t200(ctrl);
+ reschedule_t200(ctrl);
}
}
}
}
}
-
+ break;
+ case Q921_TEI_ASSIGNED:
+ case Q921_AWAITING_ESTABLISHMENT:
+ case Q921_AWAITING_RELEASE:
+ /*
+ * Ignore this frame.
+ * We likely got reset and the other end has not realized it yet.
+ */
break;
default:
pri_error(ctrl, "Don't know what to do with an I-frame in state %d(%s)\n",
@@ -1871,6 +2131,10 @@
static pri_event *q921_dm_rx(struct pri *ctrl, q921_h *h)
{
pri_event * res = NULL;
+
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Got DM\n", ctrl->tei);
+ }
switch (ctrl->q921_state) {
case Q921_TEI_ASSIGNED:
@@ -1936,6 +2200,10 @@
{
pri_event * res = NULL;
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Got RNR N(R)=%d\n", ctrl->tei, h->s.n_r);
+ }
+
switch (ctrl->q921_state) {
case Q921_MULTI_FRAME_ESTABLISHED:
ctrl->peer_rx_busy = 1;
@@ -1965,23 +2233,14 @@
if (is_command(ctrl, h)) {
if (h->s.p_f) {
q921_enquiry_response(ctrl);
- if (n_r_is_valid(ctrl, h->s.n_r)) {
- update_v_a(ctrl, h->s.n_r);
- break;
- } else {
- n_r_error_recovery(ctrl);
- q921_setstate(ctrl, Q921_AWAITING_ESTABLISHMENT);
- break;
- }
+ }
+ if (n_r_is_valid(ctrl, h->s.n_r)) {
+ update_v_a(ctrl, h->s.n_r);
+ break;
} else {
- if (n_r_is_valid(ctrl, h->s.n_r)) {
- update_v_a(ctrl, h->s.n_r);
- break;
- } else {
- n_r_error_recovery(ctrl);
- q921_setstate(ctrl, Q921_AWAITING_ESTABLISHMENT);
- break;
- }
+ n_r_error_recovery(ctrl);
+ q921_setstate(ctrl, Q921_AWAITING_ESTABLISHMENT);
+ break;
}
} else {
if (h->s.p_f) {
@@ -2008,6 +2267,14 @@
}
}
break;
+ case Q921_TEI_ASSIGNED:
+ case Q921_AWAITING_ESTABLISHMENT:
+ case Q921_AWAITING_RELEASE:
+ /*
+ * Ignore this frame.
+ * We likely got reset and the other end has not realized it yet.
+ */
+ break;
default:
pri_error(ctrl, "Don't know what to do with RNR in state %d(%s)\n",
ctrl->q921_state, q921_state2str(ctrl->q921_state));
@@ -2042,6 +2309,7 @@
static pri_event *__q921_receive_qualified(struct pri *ctrl, q921_h *h, int len)
{
+ int res;
pri_event *ev = NULL;
switch(h->h.data[0] & Q921_FRAMETYPE_MASK) {
@@ -2050,22 +2318,20 @@
ev = q921_iframe_rx(ctrl, h, len);
break;
case 1:
- switch(h->s.ss) {
- case 0:
- ev = q921_rr_rx(ctrl, h);
- break;
- case 1:
+ switch ((h->s.x0 << 2) | h->s.ss) {
+ case 0x00:
+ ev = q921_rr_rx(ctrl, h);
+ break;
+ case 0x01:
ev = q921_rnr_rx(ctrl, h);
break;
- case 2:
- /* Just retransmit */
- if (ctrl->debug & PRI_DEBUG_Q921_STATE)
- pri_message(ctrl, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
+ case 0x02:
ev = q921_rej_rx(ctrl, h);
break;
default:
- pri_error(ctrl, "!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,
- ctrl->v_s, ctrl->v_a);
+ pri_error(ctrl,
+ "!! XXX Unknown Supervisory frame x0=%d ss=%d, pf=%d, N(R)=%d, V(A)=%d, V(S)=%d XXX\n",
+ h->s.x0, h->s.ss, h->s.p_f, h->s.n_r, ctrl->v_a, ctrl->v_s);
break;
}
break;
@@ -2074,69 +2340,58 @@
pri_error(ctrl, "!! Received short unnumbered frame\n");
break;
}
- switch(h->u.m3) {
- case 0:
- if (h->u.m2 == 3) {
- ev = q921_dm_rx(ctrl, h);
- break;
- } else if (!h->u.m2) {
- if ((ctrl->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (ctrl->tei == Q921_TEI_GROUP)) {
- pri_error(ctrl, "I should never be called\n");
- ev = q921_receive_MDL(ctrl, (q921_u *)h, len);
- } else {
- int res;
-
- res = q931_receive(ctrl, ctrl->tei, (q931_h *) h->u.data, len - 3);
- if (res != -1 && (res & Q931_RES_HAVEEVENT)) {
- ev = &ctrl->ev;
- }
+ switch ((h->u.m3 << 2) | h->u.m2) {
+ case 0x03:
+ ev = q921_dm_rx(ctrl, h);
+ break;
+ case 0x00:
+ /* UI-frame */
+ res = q931_receive(ctrl, ctrl->tei, (q931_h *) h->u.data, len - 3);
+ if (res != -1 && (res & Q931_RES_HAVEEVENT)) {
+ ev = &ctrl->ev;
+ }
+ break;
+ case 0x08:
+ ev = q921_disc_rx(ctrl, h);
+ break;
+ case 0x0F:
+ /* SABME */
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
+ pri_message(ctrl, "TEI=%d Got SABME from %s peer.\n",
+ ctrl->tei, h->h.c_r ? "network" : "cpe");
+ }
+ if (h->h.c_r) {
+ ctrl->remotetype = PRI_NETWORK;
+ if (ctrl->localtype == PRI_NETWORK) {
+ /* We can't both be networks */
+ ev = pri_mkerror(ctrl, "We think we're the network, but they think they're the network, too.");
+ break;
}
- }
- break;
- case 2:
- ev = q921_disc_rx(ctrl, h);
- break;
- case 3:
- if (h->u.m2 == 3) {
- /* SABME */
- if (ctrl->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) {
- pri_message(ctrl, "-- Got SABME from %s peer.\n", h->h.c_r ? "network" : "cpe");
+ } else {
+ ctrl->remotetype = PRI_CPE;
+ if (ctrl->localtype == PRI_CPE) {
+ /* We can't both be CPE */
+ ev = pri_mkerror(ctrl, "We think we're the CPE, but they think they're the CPE too.\n");
+ break;
}
- if (h->h.c_r) {
- ctrl->remotetype = PRI_NETWORK;
- if (ctrl->localtype == PRI_NETWORK) {
- /* We can't both be networks */
- ev = pri_mkerror(ctrl, "We think we're the network, but they think they're the network, too.");
- break;
- }
- } else {
- ctrl->remotetype = PRI_CPE;
- if (ctrl->localtype == PRI_CPE) {
- /* We can't both be CPE */
- ev = pri_mkerror(ctrl, "We think we're the CPE, but they think they're the CPE too.\n");
- break;
- }
- }
- ev = q921_sabme_rx(ctrl, h);
- break;
- } else if (h->u.m2 == 0) {
- ev = q921_ua_rx(ctrl, h);
- break;
- } else
- pri_error(ctrl, "!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2);
- break;
- case 4:
- pri_error(ctrl, "!! Frame got rejected!\n");
- break;
- case 5:
+ }
+ ev = q921_sabme_rx(ctrl, h);
+ break;
+ case 0x0C:
+ ev = q921_ua_rx(ctrl, h);
+ break;
+ case 0x11:
+ ev = q921_frmr_rx(ctrl, h);
+ break;
+ case 0x17:
pri_error(ctrl, "!! XID frames not supported\n");
break;
default:
- pri_error(ctrl, "!! Don't know what to do with M3=%d u-frames\n", h->u.m3);
- break;
- }
- break;
-
+ pri_error(ctrl, "!! Don't know what to do with u-frame (m3=%d, m2=%d)\n",
+ h->u.m3, h->u.m2);
+ break;
+ }
+ break;
}
q921_statemachine_check(ctrl);
@@ -2160,7 +2415,7 @@
/* If we're NT-PTMP, this means an unrecognized TEI that we'll kill */
if (BRI_NT_PTMP(ctrl)) {
- if (ctrl->debug & PRI_DEBUG_Q921_DUMP) {
+ if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
pri_message(ctrl,
"Could not find candidate subchannel for received frame with SAPI/TEI of %d/%d.\n",
h->h.sapi, h->h.tei);
@@ -2180,47 +2435,52 @@
{
pri_event *ev = NULL;
struct pri *tei;
+
/* Discard FCS */
len -= 2;
- if (ctrl->debug & (PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW))
+ if (ctrl->debug & (PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW)) {
q921_dump(ctrl, h, len, ctrl->debug & PRI_DEBUG_Q921_RAW, 0);
+ }
/* Check some reject conditions -- Start by rejecting improper ea's */
- if (h->h.ea1 || !(h->h.ea2))
+ if (h->h.ea1 || !h->h.ea2) {
return NULL;
-
- if ((h->h.sapi == Q921_SAPI_LAYER2_MANAGEMENT)) {
+ }
+
+ if (h->h.sapi == Q921_SAPI_LAYER2_MANAGEMENT) {
return q921_receive_MDL(ctrl, &h->u, len);
}
[... 41 lines stripped ...]
More information about the libpri-commits
mailing list