[libpri-commits] mattf: branch mattf/libpri-1.4-q921-rewrite r1129 - /team/mattf/libpri-1.4-q9...
SVN commits to the libpri project
libpri-commits at lists.digium.com
Tue Sep 22 15:36:46 CDT 2009
Author: mattf
Date: Tue Sep 22 15:36:43 2009
New Revision: 1129
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1129
Log:
Commit current code in rewite. Seems to be functional, and probably ready to start testing to prepare for commit.
Modified:
team/mattf/libpri-1.4-q921-rewrite/pri.c
team/mattf/libpri-1.4-q921-rewrite/pri_internal.h
team/mattf/libpri-1.4-q921-rewrite/pri_q921.h
team/mattf/libpri-1.4-q921-rewrite/q921.c
team/mattf/libpri-1.4-q921-rewrite/q931.c
Modified: team/mattf/libpri-1.4-q921-rewrite/pri.c
URL: http://svnview.digium.com/svn/libpri/team/mattf/libpri-1.4-q921-rewrite/pri.c?view=diff&rev=1129&r1=1128&r2=1129
==============================================================================
--- team/mattf/libpri-1.4-q921-rewrite/pri.c (original)
+++ team/mattf/libpri-1.4-q921-rewrite/pri.c Tue Sep 22 15:36:43 2009
@@ -306,11 +306,15 @@
int pri_restart(struct pri *pri)
{
+#if 0
/* Restart Q.921 layer */
if (pri) {
q921_reset(pri);
q921_start(pri, pri->localtype == PRI_CPE);
}
+#else
+ pri_error(pri, "pri_restart should never be called !!!!\n");
+#endif
return 0;
}
Modified: team/mattf/libpri-1.4-q921-rewrite/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/team/mattf/libpri-1.4-q921-rewrite/pri_internal.h?view=diff&rev=1129&r1=1128&r2=1129
==============================================================================
--- team/mattf/libpri-1.4-q921-rewrite/pri_internal.h (original)
+++ team/mattf/libpri-1.4-q921-rewrite/pri_internal.h Tue Sep 22 15:36:43 2009
@@ -73,6 +73,13 @@
/* Q.921 State */
int q921_state;
+ int k;
+ int RC;
+ int peer_rx_busy:1;
+ int own_rx_busy:1;
+ int acknowledge_pending:1;
+ int reject_exception:1;
+
int window; /* Max window size */
int windowlen; /* Fullness of window */
int v_s; /* Next N(S) for transmission */
@@ -86,6 +93,7 @@
int cref; /* Next call reference value */
int busy; /* Peer is busy */
+ int l3initiated;
/* Various timers */
int sabme_timer; /* SABME retransmit */
Modified: team/mattf/libpri-1.4-q921-rewrite/pri_q921.h
URL: http://svnview.digium.com/svn/libpri/team/mattf/libpri-1.4-q921-rewrite/pri_q921.h?view=diff&rev=1129&r1=1128&r2=1129
==============================================================================
--- team/mattf/libpri-1.4-q921-rewrite/pri_q921.h (original)
+++ team/mattf/libpri-1.4-q921-rewrite/pri_q921.h Tue Sep 22 15:36:43 2009
@@ -166,19 +166,31 @@
} q921_frame;
#define Q921_INC(j) (j) = (((j) + 1) % 128)
+#define Q921_DEC(j) (j) = (((j) - 1) % 128)
typedef enum q921_state {
Q921_DOWN = 0,
- Q921_TEI_UNASSIGNED,
- Q921_TEI_AWAITING_ESTABLISH,
- Q921_TEI_AWAITING_ASSIGN,
- Q921_TEI_ASSIGNED,
+ /* All states except Q921_DOWN are defined in Q.921 SDL diagrams */
+ Q921_TEI_UNASSIGNED = 1,
+ Q921_ASSIGN_AWAITING_TEI = 2,
+ Q921_ESTABLISH_AWAITING_TEI = 3,
+ Q921_TEI_ASSIGNED = 4,
+ Q921_LINK_CONNECTION_RELEASED = 4, /* Also known as TEI_ASSIGNED */
+ Q921_AWAITING_ESTABLISH = 5,
+ Q921_AWAITING_ESTABLISHMENT = 5,
+ Q921_AWAITING_RELEASE = 6,
+ Q921_MULTI_FRAME_ESTABLISHED = 7,
+ Q921_LINK_CONNECTION_ESTABLISHED = 7,
+ Q921_TIMER_RECOVERY = 8,
+#if 1
Q921_NEGOTIATION,
- Q921_LINK_CONNECTION_RELEASED, /* Also known as TEI_ASSIGNED */
- Q921_LINK_CONNECTION_ESTABLISHED,
- Q921_AWAITING_ESTABLISH,
- Q921_AWAITING_RELEASE
+#endif
} q921_state;
+
+static inline int Q921_ADD(int a, int b)
+{
+ return (a + b) % 128;
+}
/* Dumps a *known good* Q.921 packet */
extern void q921_dump(struct pri *pri, q921_h *h, int len, int showraw, int txrx);
@@ -186,14 +198,14 @@
/* Bring up the D-channel */
extern void q921_start(struct pri *pri, int now);
-extern void q921_reset(struct pri *pri);
+//extern void q921_reset(struct pri *pri);
extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len);
extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
-extern pri_event *q921_dchannel_up(struct pri *pri);
-
-extern pri_event *q921_dchannel_down(struct pri *pri);
-
-#endif
+//extern pri_event *q921_dchannel_up(struct pri *pri);
+
+//extern pri_event *q921_dchannel_down(struct pri *pri);
+
+#endif
Modified: team/mattf/libpri-1.4-q921-rewrite/q921.c
URL: http://svnview.digium.com/svn/libpri/team/mattf/libpri-1.4-q921-rewrite/q921.c?view=diff&rev=1129&r1=1128&r2=1129
==============================================================================
--- team/mattf/libpri-1.4-q921-rewrite/q921.c (original)
+++ team/mattf/libpri-1.4-q921-rewrite/q921.c Tue Sep 22 15:36:43 2009
@@ -55,10 +55,18 @@
(hf).h.tei = (pri)->tei; \
} while(0)
-static void reschedule_t203(struct pri *pri);
+//static void reschedule_t203(struct pri *pri);
static void reschedule_t200(struct pri *pri);
-static void q921_restart(struct pri *pri, int now);
+//static void q921_restart(struct pri *pri, int now);
static void q921_tei_release_and_reacquire(struct pri *master);
+static void q921_establish_data_link(struct pri *pri);
+
+static void q921_setstate(struct pri *pri, int newstate)
+{
+ if ((pri->q921_state != newstate) && (newstate != 7) && (newstate != 8))
+ pri_error(pri, "Changing from state %d to %d\n", pri->q921_state, newstate);
+ pri->q921_state = newstate;
+}
static void q921_discard_retransmissions(struct pri *pri)
{
@@ -71,6 +79,11 @@
free(p);
}
pri->txqueue = NULL;
+}
+
+static void q921_discard_iqueue(struct pri *pri)
+{
+ q921_discard_retransmissions(pri);
}
static int q921_transmit(struct pri *pri, q921_h *h, int len)
@@ -167,6 +180,7 @@
q921_transmit(pri, &h, 3);
}
+#if 0
static void q921_send_sabme_now(void *vpri);
static void q921_send_sabme(void *vpri, int now)
@@ -208,19 +222,45 @@
q921_transmit(pri, &h, 3);
if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_AWAITING_ESTABLISH)
pri_message(pri, DBGHEAD "q921_state now is Q921_AWAITING_ESTABLISH\n", DBGINFO);
- pri->q921_state = Q921_AWAITING_ESTABLISH;
-}
-
+ q921_setstate(pri, Q921_AWAITING_ESTABLISHMENT);
+}
+#endif
+
+static void q921_send_sabme(struct pri *pri)
+{
+ q921_h h;
+
+ Q921_INIT(pri, h);
+ h.u.m3 = 3; /* M3 = 3 */
+ h.u.m2 = 3; /* M2 = 3 */
+ h.u.p_f = 1; /* Poll bit set */
+ h.u.ft = Q921_FRAMETYPE_U;
+ switch(pri->localtype) {
+ case PRI_NETWORK:
+ h.h.c_r = 1;
+ break;
+ case PRI_CPE:
+ h.h.c_r = 0;
+ break;
+ default:
+ pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
+ return;
+ }
+ q921_transmit(pri, &h, 3);
+}
+
+#if 0
static void q921_send_sabme_now(void *vpri)
{
q921_send_sabme(vpri, 1);
}
+#endif
static int q921_ack_packet(struct pri *pri, int num)
{
struct q921_frame *f, *prev = NULL;
f = pri->txqueue;
- while(f) {
+ while (f) {
if (f->h.n_s == num) {
/* Cancel each packet as necessary */
/* That's our packet */
@@ -231,12 +271,7 @@
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1);
/* Update v_a */
- pri->v_a = num;
free(f);
- /* Reset retransmission counter if we actually acked something */
- pri->retrans = 0;
- /* Decrement window size */
- pri->windowlen--;
return 1;
}
prev = f;
@@ -256,6 +291,9 @@
pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
}
+#define restart_t200(pri) reschedule_t200((pri))
+
+#if 0
static void reschedule_t203(struct pri *pri)
{
if (pri->debug & PRI_DEBUG_Q921_DUMP)
@@ -263,32 +301,129 @@
pri_schedule_del(pri, pri->t203_timer);
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
}
-
-static void q921_send_queued_iframes(struct pri *pri)
+#endif
+
+#if 0
+static int q921_unacked_iframes(struct pri *pri)
+{
+ struct q921_frame *f = pri->txqueue;
+ int cnt = 0;
+
+ while(f) {
+ if (f->transmitted)
+ cnt++;
+ f = f->next;
+ }
+
+ return cnt;
+}
+#endif
+
+static void start_t203(struct pri *pri)
+{
+ if (pri->t203_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "T203 requested to start without stopping first\n");
+ pri_schedule_del(pri, pri->t203_timer);
+ }
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Starting T203 timer\n");
+ pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
+}
+
+static void stop_t203(struct pri *pri)
+{
+ if (pri->t203_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Stopping T203 timer\n");
+ pri_schedule_del(pri, pri->t203_timer);
+ pri->t203_timer = 0;
+ } else {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- T203 requested to stop when not started\n");
+ }
+}
+
+static void start_t200(struct pri *pri)
+{
+ if (pri->t200_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "T200 requested to start without stopping first\n");
+ pri_schedule_del(pri, pri->t200_timer);
+ }
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Starting T200 timer\n");
+ pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
+}
+
+static void stop_t200(struct pri *pri)
+{
+#if 0
+ if (pri->sabme_timer) {
+ pri_schedule_del(pri, pri->sabme_timer);
+ pri->sabme_timer = 0;
+ }
+#endif
+ if (pri->t200_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Stopping T200 timer\n");
+ pri_schedule_del(pri, pri->t200_timer);
+ pri->t200_timer = 0;
+ } else {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- T200 requested to stop when not started\n");
+ }
+}
+
+/* This is the equivalent of the I-Frame queued up path in Figure B.7 in MULTI_FRAME_ESTABLISHED */
+static int q921_send_queued_iframes(struct pri *pri)
{
struct q921_frame *f;
+ int frames_txd = 0;
+
+ if (pri->peer_rx_busy || (pri->v_s == Q921_ADD(pri->v_a, pri->k))) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "Couldn't transmit I frame at this time due to peer busy condition or window shut\n");
+ return 0;
+ }
f = pri->txqueue;
- while(f && (pri->windowlen < pri->window)) {
+ while (f && (pri->v_s != Q921_ADD(pri->v_a, pri->k))) {
if (!f->transmitted) {
/* Send it now... */
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- Finally transmitting %d, since window opened up (%d)\n", f->h.n_s, pri->windowlen);
f->transmitted++;
- pri->windowlen++;
+ f->h.n_s = pri->v_s;
f->h.n_r = pri->v_r;
+// pri->v_na = pri->v_r;
+ f->h.ft = 0;
f->h.p_f = 0;
q921_transmit(pri, (q921_h *)(&f->h), f->len);
+ Q921_INC(pri->v_s);
+ frames_txd++;
+ pri->acknowledge_pending = 0;
}
f = f->next;
}
-}
-
+
+ if (frames_txd) {
+ if (!pri->t200_timer) {
+ stop_t203(pri);
+ start_t200(pri);
+ }
+ }
+
+ return frames_txd;
+}
+
+#if 0
static pri_event *q921_ack_rx(struct pri *pri, int ack, int send_untransmitted_frames)
{
int x;
int cnt=0;
pri_event *ev;
+ int txd_frames = 0;
/* Make sure the ACK was within our window */
for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x));
if (x != ack) {
@@ -317,24 +452,47 @@
pri_schedule_del(pri, pri->t203_timer);
pri->t203_timer = 0;
}
+
+ /* We ACK'd some frames */
+ if (cnt) {
+ stop_t200(pri);
+ }
+
+ if (send_untransmitted_frames) {
+ txd_frames = q921_send_queued_iframes(pri);
+ }
+
+ if (txd_frames || q921_unacked_iframes(pri)) {
+ if (!pri->t200_timer) {
+ start_t200(pri);
+ }
+ }
+
+ if (!pri->t200_timer) {
+ start_t203(pri);
+ }
+
+#if 0
if (pri->txqueue) {
/* Something left to transmit, Start the T200 counter again if we stopped it */
if (!pri->busy && send_untransmitted_frames) {
pri->retrans = 0;
/* Search for something to send */
- q921_send_queued_iframes(pri);
- }
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Waiting for acknowledge, restarting T200 counter\n");
- reschedule_t200(pri);
+ txd_frames = q921_send_queued_iframes(pri);
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Waiting for acknowledge, restarting T200 counter\n");
+ reschedule_t200(pri);
+ }
} else {
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- Nothing left, starting T203 counter\n");
/* Nothing to transmit, start the T203 counter instead */
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
}
+#endif
return NULL;
}
+#endif
static void q921_reject(struct pri *pri, int pf)
{
@@ -358,7 +516,6 @@
}
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "Sending Reject (%d)\n", pri->v_r);
- pri->sentrej = 1;
q921_transmit(pri, &h, 4);
}
@@ -387,13 +544,76 @@
pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
return;
}
- pri->v_na = pri->v_r; /* Make a note that we've already acked this */
+ //pri->v_na = pri->v_r; /* Make a note that we've already acked this */
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "Sending Receiver Ready (%d)\n", pri->v_r);
q921_transmit(pri, &h, 4);
}
+static void transmit_enquiry(struct pri *pri)
+{
+ if (!pri->own_rx_busy) {
+ q921_rr(pri, 1, 1);
+ pri->acknowledge_pending = 0;
+ start_t200(pri);
+ } else {
+ /* XXX: Implement me... */
+ }
+}
+
static void t200_expire(void *vpri)
+{
+ struct pri *pri = vpri;
+
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "%s\n", __FUNCTION__);
+
+ pri->t200_timer = 0;
+
+ switch (pri->q921_state) {
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ pri->RC = 0;
+ transmit_enquiry(pri);
+ pri->RC++;
+ q921_setstate(pri, Q921_TIMER_RECOVERY);
+ break;
+ case Q921_TIMER_RECOVERY:
+ if (pri->RC != pri->timers[PRI_TIMER_N200]) {
+ if (pri->v_s == pri->v_a) {
+ transmit_enquiry(pri);
+ }
+ pri->RC++;
+ } else {
+ pri_error(pri, "MDL-ERROR (I): T200 = N200 in timer recovery state\n");
+ q921_establish_data_link(pri);
+ pri->l3initiated = 0;
+ q921_setstate(pri, Q921_AWAITING_ESTABLISHMENT);
+ }
+ break;
+ case Q921_AWAITING_ESTABLISHMENT:
+ if (pri->RC != pri->timers[PRI_TIMER_N200]) {
+ pri->RC++;
+ q921_send_sabme(pri);
+ start_t200(pri);
+ } else {
+ q921_discard_iqueue(pri);
+ pri_error(pri, "MDL-ERROR (G) : T200 expired N200 times in state %d\n", pri->q921_state);
+ /* Deviation - We're still going to try to go back to multiframe established */
+ q931_dl_indication(pri, PRI_EVENT_DCHAN_DOWN);
+ pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
+ pri->schedev = 1;
+ pri->RC = 0;
+ start_t200(pri);
+ }
+ break;
+ default:
+ pri_error(pri, "Cannot handle T200 expire in state %d\n", pri->q921_state);
+ }
+
+}
+
+#if 0
+static void t200_expire_old(void *vpri)
{
struct pri *pri = vpri;
q921_frame *f, *lastframe=NULL;
@@ -476,71 +696,92 @@
pri->t200_timer = 0;
}
}
-
+#endif
+
+/* This is the equivalent of a DL-DATA request, as well as the I frame queued up outcome */
int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
{
q921_frame *f, *prev=NULL;
- for (f=pri->txqueue; f; f = f->next) prev = f;
- f = calloc(1, sizeof(q921_frame) + len + 2);
- if (f) {
- Q921_INIT(pri, f->h);
- switch(pri->localtype) {
- case PRI_NETWORK:
- if (cr)
- f->h.h.c_r = 1;
+ /* Figure B.7/Q.921 Page 70 */
+ switch (pri->q921_state) {
+ case Q921_TIMER_RECOVERY:
+ case Q921_AWAITING_ESTABLISHMENT:
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ for (f=pri->txqueue; f; f = f->next) prev = f;
+ f = calloc(1, sizeof(q921_frame) + len + 2);
+ if (f) {
+ Q921_INIT(pri, f->h);
+ switch(pri->localtype) {
+ case PRI_NETWORK:
+ if (cr)
+ f->h.h.c_r = 1;
+ else
+ f->h.h.c_r = 0;
+ break;
+ case PRI_CPE:
+ if (cr)
+ f->h.h.c_r = 0;
+ else
+ f->h.h.c_r = 1;
+ break;
+ }
+ f->next = NULL;
+ f->transmitted = 0;
+ f->len = len + 4;
+ memcpy(f->h.data, buf, len);
+ if (prev)
+ prev->next = f;
else
- f->h.h.c_r = 0;
- break;
- case PRI_CPE:
- if (cr)
- f->h.h.c_r = 0;
- else
- f->h.h.c_r = 1;
- break;
- }
- f->next = NULL;
- f->transmitted = 0;
- f->len = len + 4;
- memcpy(f->h.data, buf, len);
- f->h.n_s = pri->v_s;
- f->h.n_r = pri->v_r;
- pri->v_s++;
- pri->v_na = pri->v_r;
- f->h.p_f = 0;
- f->h.ft = 0;
- if (prev)
- prev->next = f;
- else
- pri->txqueue = f;
- /* Immediately transmit unless we're in a recovery state, or the window
- size is too big */
- if ((pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) && (!pri->retrans && !pri->busy)) {
- if (pri->windowlen < pri->window) {
- q921_send_queued_iframes(pri);
- } else {
+ pri->txqueue = f;
+
+ if (pri->q921_state != Q921_MULTI_FRAME_ESTABLISHED) {
+ return 0;
+ }
+
+ if (pri->peer_rx_busy || (pri->v_s == Q921_ADD(pri->v_a, pri->k))) {
if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "Delaying transmission of %d, window is %d/%d long\n",
- f->h.n_s, pri->windowlen, pri->window);
- }
- }
- if (pri->t203_timer) {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "Stopping T_203 timer\n");
- pri_schedule_del(pri, pri->t203_timer);
- pri->t203_timer = 0;
- }
-
- /* Check this so that we don't try to send frames while multi frame mode is down */
- if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "Starting T_200 timer\n");
-
- reschedule_t200(pri);
- }
- } else {
- pri_error(pri, "!! Out of memory for Q.921 transmit\n");
- return -1;
+ pri_message(pri, "Couldn't transmit I frame at this time due to peer busy condition or window shut\n");
+ return 0;
+ }
+
+ q921_send_queued_iframes(pri);
+
+ return 0;
+#if 0
+ /* Immediately transmit unless we're in a recovery state, or the window
+ size is too big */
+ if ((pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) && (!pri->retrans && !pri->busy)) {
+ if (pri->windowlen < pri->window) {
+ new_frames_sent = q921_send_queued_iframes(pri);
+ if (new_frames_sent) {
+ if (pri->t203_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "Stopping T_203 timer\n");
+ pri_schedule_del(pri, pri->t203_timer);
+ pri->t203_timer = 0;
+ }
+
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "Starting T_200 timer\n");
+
+ /* Only start T200 if we sent new frames and if T200 is not running already */
+ if (!pri->t200_timer)
+ reschedule_t200(pri);
+ }
+ } else {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "Delaying transmission of %d, window is %d/%d long\n",
+ f->h.n_s, pri->windowlen, pri->window);
+ }
+ }
+#endif
+ } else {
+ pri_error(pri, "!! Out of memory for Q.921 transmit\n");
+ return -1;
+ }
+ default:
+ pri_error(pri, "Cannot transmit frames in state %d\n", pri->q921_state);
}
return 0;
}
@@ -548,6 +789,22 @@
static void t203_expire(void *vpri)
{
struct pri *pri = vpri;
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "%s\n", __FUNCTION__);
+ pri->t203_timer = 0;
+ switch (pri->q921_state) {
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ transmit_enquiry(pri);
+ pri->RC = 0;
+ q921_setstate(pri, Q921_TIMER_RECOVERY);
+ break;
+ default:
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state);
+ pri->t203_timer = 0;
+ break;
+ }
+#if 0
if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "T203 counter expired, sending RR and scheduling T203 again\n");
@@ -556,13 +813,16 @@
pri->retrans = 0;
q921_rr(pri, 1, 1);
/* Start timer T200 to resend our RR if we don't get it */
- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
+ pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
} else {
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state);
pri->t203_timer = 0;
}
-}
+#endif
+}
+
+#if 0
static pri_event *q921_handle_iframe(struct pri *pri, q921_i *i, int len)
{
int res;
@@ -604,6 +864,30 @@
}
return NULL;
}
+#endif
+
+static void q921_dump_iqueue_info(struct pri *pri, int force)
+{
+ struct q921_frame *f;
+ int pending = 0, unacked = 0;
+
+ unacked = pending = 0;
+
+ for (f = pri->txqueue; f && f->next; f = f->next) {
+ if (f->transmitted) {
+ unacked++;
+ } else {
+ pending++;
+ }
+ }
+
+ if (force)
+ pri_error(pri, "Number of pending packets %d, sent but unacked %d\n", pending, unacked);
+
+ return;
+}
+
+static void q921_dump_pri(struct pri *pri);
void q921_dump(struct pri *pri, q921_h *h, int len, int showraw, int txrx)
{
@@ -611,6 +895,8 @@
char *type;
char direction_tag;
+ q921_dump_pri(pri);
+
direction_tag = txrx ? '>' : '<';
if (showraw) {
char *buf = malloc(len * 3 + 1);
@@ -783,8 +1069,11 @@
}
}
+#if 0
pri_event *q921_dchannel_up(struct pri *pri)
{
+ pri_error(pri, "%s\n", __FUNCTION__);
+ q921_reset(pri);
/* Stop any SABME retransmissions */
pri_schedule_del(pri, pri->sabme_timer);
pri->sabme_timer = 0;
@@ -809,9 +1098,12 @@
pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
return &pri->ev;
}
-
+#endif
+
+#if 0
pri_event *q921_dchannel_down(struct pri *pri)
{
+ pri_error(pri, "%s\n", __FUNCTION__);
/* Reset counters, reset sabme timer etc */
q921_reset(pri);
@@ -822,9 +1114,21 @@
pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
return &pri->ev;
}
-
+#endif
+
+static void q921_dump_pri(struct pri *pri)
+{
+ pri_message(pri, "State %d\n", pri->q921_state);
+ pri_message(pri, "V(S) %d V(A) %d V(R) %d V(NA) %d\n", pri->v_s, pri->v_a, pri->v_r, pri->v_na);
+ pri_message(pri, "K %d, RC %d, l3initiated %d, reject_except %d ack_pend %d\n", pri->k, pri->RC, pri->l3initiated, pri->reject_exception, pri->acknowledge_pending);
+ //pri_message(pri, "Window %d Windowlen %d, sentrej %d solicitfbit %d busy %d\n", pri->window, pri->windowlen, pri->sentrej, pri->solicitfbit, pri->busy);
+ pri_message(pri, "T200 %d, N200 %d, T203 %d, Sabme timer %d\n", pri->t200_timer, 3, pri->t203_timer, pri->sabme_timer);
+}
+
+#if 0
void q921_reset(struct pri *pri)
{
+ pri_error(pri, "%s\n", __FUNCTION__);
/* Having gotten a SABME we MUST reset our entire state */
pri->v_s = 0;
pri->v_a = 0;
@@ -848,13 +1152,14 @@
pri->sentrej = 0;
/* Discard anything waiting to go out */
- q921_discard_retransmissions(pri);
-}
+ q921_discard_iqueue(pri);
+}
+#endif
static void q921_tei_release_and_reacquire(struct pri *master)
{
/* Make sure the master is passed into this function */
- q921_dchannel_down(master->subchannel);
+ //q921_dchannel_down(master->subchannel);
__pri_free_tei(master->subchannel);
master->subchannel = NULL;
master->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
@@ -919,7 +1224,7 @@
pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
return NULL;
}
- pri->q921_state = Q921_TEI_ASSIGNED;
+ q921_setstate(pri, Q921_TEI_ASSIGNED);
break;
case Q921_TEI_IDENTITY_CHECK_REQUEST:
/* We're assuming one TEI per PRI in TE PTMP mode */
@@ -957,15 +1262,449 @@
return( command );
}
+static void q921_clear_exception_conditions(struct pri *pri)
+{
+ pri->own_rx_busy = 0;
+ pri->peer_rx_busy = pri->busy = 0;
+ pri->reject_exception = pri->sentrej = 0;
+ pri->acknowledge_pending = 0;
+}
+
+static pri_event * q921_sabme_rx(struct pri *pri, q921_h *h)
+{
+ pri_event *res = NULL;
+
+ switch (pri->q921_state) {
+ case Q921_TIMER_RECOVERY:
+ /* Timer recovery state handling is same as multiframe established */
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ /* Send Unnumbered Acknowledgement */
+ q921_send_ua(pri, h->u.p_f);
+ q921_clear_exception_conditions(pri);
+ pri_error(pri, "MDL-ERROR (F), SABME in state %d\n", pri->q921_state);
+ if (pri->v_s != pri->v_a) {
+ q921_discard_iqueue(pri);
+ pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
+ res = &pri->ev;
+ }
+ stop_t200(pri);
+ start_t203(pri);
+ pri->v_s = pri->v_a = pri->v_r = 0;
+ q921_setstate(pri, Q921_MULTI_FRAME_ESTABLISHED);
+ break;
+ case Q921_TEI_ASSIGNED:
+ q921_send_ua(pri, h->u.p_f);
+ q921_clear_exception_conditions(pri);
+ pri->v_s = pri->v_a = pri->v_r = 0;
+ pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
+ res = &pri->ev;
+ start_t203(pri);
+ q921_setstate(pri, Q921_MULTI_FRAME_ESTABLISHED);
+ break;
+ case Q921_AWAITING_ESTABLISHMENT:
+ q921_send_ua(pri, h->u.p_f);
+ break;
+ case Q921_AWAITING_RELEASE:
+ default:
+ pri_error(pri, "Cannot handle SABME in state %d\n", pri->q921_state);
+ }
+
+ return res;
+}
+
+#if 0
+static void stop_sabme_timer(struct pri *pri)
+{
+ if (pri->sabme_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Stopping SABME timer\n");
+ pri_schedule_del(pri, pri->sabme_timer);
+ pri->sabme_timer = 0;
+ } else {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Requested to stop already stopped SABME timer\n");
+ }
+}
+#endif
+
+static pri_event *q921_ua_rx(struct pri *pri, q921_h *h)
+{
+ pri_event * res = NULL;
+
+ switch (pri->q921_state) {
+ case Q921_TEI_ASSIGNED:
+ pri_error(pri, "MDL-ERROR (C, D): UA received in state %d\n", pri->q921_state);
+ break;
+ case Q921_AWAITING_ESTABLISH:
+ if (!h->u.p_f) {
+ pri_error(pri, "MDL-ERROR: Received UA with F = 0 while awaiting establishment\n");
+ break;
+ }
+
+ if (!pri->l3initiated) {
+ if (pri->v_s != pri->v_a) {
+ q921_discard_iqueue(pri);
+ /* return DL-ESTABLISH-INDICATION */
+ }
+ } else {
+ /* Might not want this... */
+ pri->l3initiated = 0;
+ /* But do want this */
+ pri->v_r = 0;
+ /* return DL-ESTABLISH-CONFIRM */
+ }
+
+ pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
+ res = &pri->ev;
+
+ stop_t200(pri);
+ start_t203(pri);
+
+ pri->v_s = pri->v_a = 0;
+
+ q921_setstate(pri, Q921_MULTI_FRAME_ESTABLISHED);
+ break;
+ case Q921_AWAITING_RELEASE:
+ if (!h->u.p_f) {
+ pri_error(pri, "MDL-ERROR (D): UA in state %d w with P_F bit 0\n", pri->q921_state);
+ } else {
+ /* return DL-RELEASE-CONFIRM */
+ stop_t200(pri);
+ q921_setstate(pri, Q921_TEI_ASSIGNED);
+ }
+ break;
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ case Q921_TIMER_RECOVERY:
+ pri_error(pri, "MDL-ERROR (C, D) UA in state %d\n", pri->q921_state);
+ break;
+ default:
+ pri_error(pri, "Don't know what to do with UA in state %d\n", pri->q921_state);
+ break;
+
+ }
+
+ return res;
+}
+
+static void q921_enquiry_response(struct pri *pri)
+{
+ if (pri->own_rx_busy) {
+ pri_error(pri, "Implement me %s: own_rx_busy\n", __FUNCTION__);
+ //q921_rnr(pri);
+ } else {
+ q921_rr(pri, 1, 0);
+ }
+
+ pri->acknowledge_pending = 0;
+}
+
+static void n_r_error_recovery(struct pri *pri)
+{
+ pri_error(pri, "MDL-ERROR (J)\n");
+
+ q921_establish_data_link(pri);
+
+ pri->l3initiated = 0;
+}
+
+static void update_v_a(struct pri *pri, int n_r)
+{
+ int idealcnt = 0, realcnt = 0;
+ int x;
+
+ /* Cancel each packet as necessary */
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, n_r);
+ for (x = pri->v_a; x != n_r; Q921_INC(x)) {
+ idealcnt++;
+ realcnt += q921_ack_packet(pri, x);
+ }
+ if (idealcnt != realcnt) {
+ pri_error(pri, "Ideally should have ack'd %d frames, but actually ack'd %d. This is not good.\n", idealcnt, realcnt);
+ q921_dump_iqueue_info(pri, 1);
+ }
+
+ q921_dump_iqueue_info(pri, 0);
+
+ pri->v_a = n_r;
+}
+
+static int n_r_is_valid(struct pri *pri, int n_r)
+{
+ int x;
+
+ for (x=pri->v_a; (x != pri->v_s) && (x != n_r); Q921_INC(x));
+ if (x != n_r) {
+ pri_error(pri, "N(R) %d not within ack window! Bad Bad Bad!\n", n_r);
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+static int q921_invoke_retransmission(struct pri *pri, int n_r);
+
+static pri_event * timer_recovery_rr_rej_rx(struct pri *pri, q921_h *h)
+{
+ /* Figure B.7/Q.921 Page 74 */
+ pri->peer_rx_busy = 0;
+
+ if (is_command(pri, h)) {
+ if (h->s.p_f) {
+ /* Enquiry response */
+ q921_enquiry_response(pri);
+ }
+ if (n_r_is_valid(pri, h->s.n_r)) {
+ update_v_a(pri, h->s.n_r);
+ } else {
+ goto n_r_error_out;
+ }
+ } else {
+ if (!h->s.p_f) {
+ if (n_r_is_valid(pri, h->s.n_r)) {
+ update_v_a(pri, h->s.n_r);
+ } else {
+ goto n_r_error_out;
+ }
+ } else {
+ if (n_r_is_valid(pri, h->s.n_r)) {
+ update_v_a(pri, h->s.n_r);
+ stop_t200(pri);
+ start_t203(pri);
+ q921_invoke_retransmission(pri, h->s.n_r);
+ q921_setstate(pri, Q921_MULTI_FRAME_ESTABLISHED);
+ } else {
+ goto n_r_error_out;
+ }
+ }
+ }
+ return NULL;
+n_r_error_out:
+ n_r_error_recovery(pri);
+ q921_setstate(pri, Q921_AWAITING_ESTABLISHMENT);
+ return NULL;
+}
+
+static pri_event *q921_rr_rx(struct pri *pri, q921_h *h)
+{
+ pri_event * res = NULL;
+ switch (pri->q921_state) {
+ case Q921_TIMER_RECOVERY:
+ res = timer_recovery_rr_rej_rx(pri, h);
+ break;
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ /* Figure B.7/Q.921 Page 74 */
+ pri->peer_rx_busy = 0;
+
+ if (is_command(pri, h)) {
+ if (h->s.p_f) {
+ /* Enquiry response */
+ q921_enquiry_response(pri);
+ }
+ } else {
+ if (h->s.p_f) {
+ pri_message(pri, "MDL-ERROR (A): Got RR response with p_f bit set to 1 in state %d\n", pri->q921_state);
+ }
+ }
+
+ if (!n_r_is_valid(pri, h->s.n_r)) {
+ n_r_error_recovery(pri);
+ q921_setstate(pri, Q921_AWAITING_ESTABLISHMENT);
+ } else {
+ if (h->s.n_r == pri->v_s) {
+ update_v_a(pri, h->s.n_r);
+ stop_t200(pri);
+ start_t203(pri);
+ } else {
+ if (h->s.n_r != pri->v_a) {
+ /* Need to check the validity of n_r as well.. */
+ update_v_a(pri, h->s.n_r);
+ restart_t200(pri);
+ }
+ }
+ }
+ break;
+ default:
+ pri_error(pri, "Don't know what to do with RR in state %d\n", pri->q921_state);
+ break;
+ }
+
+ return res;
+}
+
+/* TODO: Look at this code more... */
+static int q921_invoke_retransmission(struct pri *pri, int n_r)
+{
+ int frames_txd = 0;
+ int frames_supposed_to_tx = 0;
+ q921_frame *f;
+ unsigned int local_v_s = pri->v_s;
+
+
+ for (f = pri->txqueue; f && (f->h.n_s != n_r); f = f->next);
+ while (f) {
+ if (f->transmitted) {
+ if (pri->debug & PRI_DEBUG_Q921_STATE)
+ pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", n_r, f->h.n_s);
+ f->h.n_r = pri->v_r;
+ f->h.p_f = 0;
+ q921_transmit(pri, (q921_h *)(&f->h), f->len);
+ frames_txd++;
+ }
+ f = f->next;
+ }
+
+ while (local_v_s != n_r) {
+ Q921_DEC(local_v_s);
+ frames_supposed_to_tx++;
+ }
+
+ if (frames_supposed_to_tx != frames_txd) {
+ pri_error(pri, "!!!!!!!!!!!! Should have only transmitted %d frames!\n", frames_supposed_to_tx);
+ }
+
+ return frames_txd;
+}
+
+static pri_event *q921_rej_rx(struct pri *pri, q921_h *h)
+{
+ pri_event * res = NULL;
+
+ pri_message(pri, "!! Got reject for frame %d in state %d\n", h->s.n_r, pri->q921_state);
+
+ switch (pri->q921_state) {
+ case Q921_TIMER_RECOVERY:
+ res = timer_recovery_rr_rej_rx(pri, h);
+ break;
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ /* Figure B.7/Q.921 Page 74 */
+ pri->peer_rx_busy = 0;
+
+ if (is_command(pri, h)) {
+ if (h->s.p_f) {
+ /* Enquiry response */
+ q921_enquiry_response(pri);
+ }
+ } else {
+ if (h->s.p_f) {
+ pri_message(pri, "MDL-ERROR (A): Got REJ response with p_f bit set to 1 in state %d\n", pri->q921_state);
+ }
+ }
+
+ if (!n_r_is_valid(pri, h->s.n_r)) {
+ n_r_error_recovery(pri);
+ q921_setstate(pri, Q921_AWAITING_ESTABLISHMENT);
+ } else {
+ update_v_a(pri, h->s.n_r);
+ stop_t200(pri);
+ start_t203(pri);
+ q921_invoke_retransmission(pri, h->s.n_r);
+ }
+ return NULL;
+ default:
+ pri_error(pri, "Don't know what to do with RR in state %d\n", pri->q921_state);
+ return NULL;
+ }
+
+ return res;
+}
+
+static pri_event *q921_iframe_rx(struct pri *pri, q921_h *h, int len)
+{
+ pri_event * eres = NULL;
+ int res = 0;
+
+ switch (pri->q921_state) {
+ case Q921_TIMER_RECOVERY:
+ case Q921_MULTI_FRAME_ESTABLISHED:
+ /* FIXME: Verify that it's a command ... */
+ if (pri->own_rx_busy) {
+ /* Note: There's a difference in th P/F between both states */
+ /* DEVIATION: Handle own rx busy */
+ }
+
+ if (h->i.n_s == pri->v_r) {
+ Q921_INC(pri->v_r);
+
+ pri->reject_exception = 0;
+
+ res = q931_receive(pri, (q931_h *)h->i.data, len - 4);
+
+ if (h->i.p_f) {
+ q921_rr(pri, 1, 0);
+ pri->acknowledge_pending = 0;
+ } else {
+ if (!pri->acknowledge_pending) {
+ /* XXX: Fix acknowledge_pending */
+ pri->acknowledge_pending = 1;
+ }
+ }
+
+ } else {
+ if (pri->reject_exception) {
+ if (h->i.p_f) {
+ q921_rr(pri, 1, 0);
+ pri->acknowledge_pending = 0;
+ }
+ } else {
+ pri->reject_exception = 1;
+ q921_reject(pri, h->i.p_f);
+ pri->acknowledge_pending = 0;
+ }
+ }
+
+ if (!n_r_is_valid(pri, h->i.n_r)) {
+ n_r_error_recovery(pri);
+ q921_setstate(pri, Q921_AWAITING_ESTABLISH);
+ } else {
+ if (pri->q921_state == Q921_TIMER_RECOVERY) {
+ update_v_a(pri, h->i.n_r);
+ break;
+ } else {
+ if (pri->peer_rx_busy) {
+ update_v_a(pri, h->i.n_r);
+ } else {
+ if (h->i.n_r == pri->v_s) {
+ update_v_a(pri, h->i.n_r);
+ stop_t200(pri);
+ start_t203(pri);
+ } else {
+ if (h->i.n_r == pri->v_a) {
+ update_v_a(pri, h->i.n_r);
+ stop_t200(pri);
+ start_t200(pri);
+ }
+ }
+ }
+ }
+ }
+
+ if (res == -1) {
+ return NULL;
+ }
+
+ if (res & Q931_RES_HAVEEVENT) {
+ return &pri->ev;
+ } else {
+ return NULL;
+ }
+ default:
+ pri_error(pri, "Don't know what to do with an I frame in state %d\n", pri->q921_state);
+ break;
+ }
+
+ return eres;
+}
+
static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
{
- q921_frame *f;
- pri_event *ev;
- int sendnow;
+ //pri_event *ev;
switch(h->h.data[0] & Q921_FRAMETYPE_MASK) {
case 0:
case 2:
+ return q921_iframe_rx(pri, h, len);
+#if 0
if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
pri_error(pri, "!! Got I-frame while link state %d\n", pri->q921_state);
return NULL;
@@ -977,7 +1716,9 @@
}
return q921_handle_iframe(pri, &h->i, len);
break;
+#endif
case 1:
+#if 0
if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
pri_error(pri, "!! Got S-frame while link down\n");
return NULL;
@@ -986,8 +1727,11 @@
pri_error(pri, "!! Received short S-frame (expected 4, got %d)\n", len);
break;
}
+#endif
switch(h->s.ss) {
case 0:
+ return q921_rr_rx(pri, h);
+#if 0
/* Receiver Ready */
pri->busy = 0;
/* Acknowledge frames as necessary */
@@ -1008,8 +1752,14 @@
q921_rr(pri, 1, 0);
}
}
+#endif
break;
case 1:
+ pri_error(pri, "%s:%d FIXME!!!\n", __FUNCTION__, __LINE__);
+
+ return NULL;
+
+#if 0
/* Receiver not ready */
if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got receiver not ready\n");
@@ -1031,10 +1781,13 @@
pri_message(pri, "Restarting T_200 timer\n");
reschedule_t200(pri);
break;
+#endif
case 2:
/* Just retransmit */
if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
+ return q921_rej_rx(pri, h);
+#if 0
if (pri->busy && !is_command(pri, h))
pri->solicitfbit = 0;
pri->busy = 0;
@@ -1071,6 +1824,7 @@
} else {
/* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */
pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
+ q921_dump(pri, h, len, 0, 0);
pri->v_a = h->s.n_r;
pri->v_s = h->s.n_r;
}
@@ -1082,6 +1836,7 @@
reschedule_t203(pri);
}
break;
+#endif
default:
pri_error(pri, "!! 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,
pri->v_s, pri->v_a);
@@ -1095,6 +1850,10 @@
switch(h->u.m3) {
case 0:
if (h->u.m2 == 3) {
+ pri_error(pri, "%s:%d FIXME!!!\n", __FUNCTION__, __LINE__);
+ return NULL;
+
+#if 0
if (h->u.p_f) {
/* Section 5.7.1 says we should restart on receiving a DM response with the f-bit set to
one, but we wait T200 first */
@@ -1114,10 +1873,14 @@
#endif
}
break;
+#endif
} else if (!h->u.m2) {
- if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP))
+ if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP)) {
+ pri_error(pri, "%s:%d FIXME!!!\n", __FUNCTION__, __LINE__);
+ return NULL;
+
q921_receive_MDL(pri, (q921_u *)h, len);
- else {
+ } else {
int res;
res = q931_receive(pri, (q931_h *) h->u.data, len - 3);
@@ -1130,6 +1893,9 @@
}
break;
case 2:
+ pri_error(pri, "%s:%d FIXME!!!\n", __FUNCTION__, __LINE__);
+ return NULL;
+#if 0
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))
pri_message(pri, "-- Got Disconnect from peer.\n");
/* Acknowledge */
@@ -1137,6 +1903,7 @@
ev = q921_dchannel_down(pri);
q921_restart(pri, 0);
return ev;
+#endif
case 3:
if (h->u.m2 == 3) {
/* SABME */
@@ -1156,10 +1923,10 @@
return pri_mkerror(pri, "We think we're the CPE, but they think they're the CPE too.\n");
}
}
- /* Send Unnumbered Acknowledgement */
- q921_send_ua(pri, h->u.p_f);
- return q921_dchannel_up(pri);
+ return q921_sabme_rx(pri, h);
} else if (h->u.m2 == 0) {
+ return q921_ua_rx(pri, h);
+#if 0
/* It's a UA */
if (pri->q921_state == Q921_AWAITING_ESTABLISH) {
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) {
@@ -1177,6 +1944,7 @@
pri_error(pri, "!! Got a UA, but i'm in state %d\n", pri->q921_state);
}
+#endif
} else
pri_error(pri, "!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2);
break;
@@ -1193,6 +1961,20 @@
}
return NULL;
+}
+
+static void q921_acknowledge_pending_check(struct pri *pri)
+{
+ if (pri->acknowledge_pending) {
+ pri->acknowledge_pending = 0;
+ q921_rr(pri, 0, 0);
+ }
+}
+
+static void q921_statemachine_check(struct pri *pri)
+{
+ q921_send_queued_iframes(pri);
+ q921_acknowledge_pending_check(pri);
}
static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len)
@@ -1227,7 +2009,7 @@
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "Handling message for SAPI/TEI=%d/%d\n", h->h.sapi, h->h.tei);
ev = __q921_receive_qualified(pri, h, len);
- reschedule_t203(pri);
+ q921_statemachine_check(pri);
return ev;
}
@@ -1241,8 +2023,13 @@
return e;
}
+#if 0
static void q921_restart(struct pri *pri, int now)
{
+ pri_error(pri, "%s\n", __FUNCTION__);
+
+ return;
+
if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
pri_error(pri, "!! q921_start: Not in 'Link Connection Released' state\n");
return;
@@ -1250,10 +2037,40 @@
/* Reset our interface */
q921_reset(pri);
/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
+ pri->q921_state = Q921_AWAITING_ESTABLISHMENT;
+
q921_send_sabme(pri, now);
}
+#endif
+
+static void q921_establish_data_link(struct pri *pri)
+{
+ pri->k = 20;
+ q921_clear_exception_conditions(pri);
+ pri->RC = 0;
+ stop_t203(pri);
+ reschedule_t200(pri);
+ q921_send_sabme(pri);
+}
void q921_start(struct pri *pri, int isCPE)
+{
+ //q921_reset(pri);
+ if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP)) {
+#ifndef NO_OLD_CODE
+ pri->q921_state = Q921_DOWN;
+ if (isCPE)
+ q921_tei_request(pri);
+#endif
+ } else {
+ q921_establish_data_link(pri);
+ pri->l3initiated = 1;
+ q921_setstate(pri, Q921_AWAITING_ESTABLISHMENT);
+ }
+}
+
+#if 0
+static void q921_start_old(struct pri *pri, int isCPE)
{
q921_reset(pri);
if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP)) {
[... 49 lines stripped ...]
More information about the libpri-commits
mailing list