Q.921/Q.931 message debug output improvements.

The Q.931 message decode debug output now will follow the correct Q.921
header decode if Q.921 message dumping is enabled.  Also the Q.931 message
decode will happen when the message actually goes out on the line instead
of when Q.931 passes the message to Q.921.  Q.921 may have to request a
TEI, bring the connection up, or retransmit previous frames before it can
actually send the new message.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1928 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
Richard Mudgett
2010-08-30 20:30:59 +00:00
parent 1fba74a1d5
commit 0089f4777a
2 changed files with 114 additions and 65 deletions

36
q921.c
View File

@@ -525,6 +525,18 @@ static int q921_send_queued_iframes(struct pri *ctrl)
q921_transmit(ctrl, (q921_h *)(&f->h), f->len);
Q921_INC(ctrl->v_s);
++frames_txd;
if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
/*
* The transmit operation might dump the Q.921 header, so logging
* the Q.931 message body after the transmit puts the sections of
* the message in the right order in the log.
*
* Also the dump is done here so the Q.931 part is decoded only
* once instead of for every retransmission.
*/
q931_dump(ctrl, ctrl->tei, (q931_h *) f->h.data, f->len - 4, 1);
}
}
if (frames_txd) {
@@ -643,7 +655,6 @@ static void t200_expire(void *vpri)
#endif
ctrl->RC++;
} else {
//pri_error(ctrl, "MDL-ERROR (I): T200 = N200 in timer recovery state\n");
q921_mdl_error(ctrl, 'I');
q921_establish_data_link(ctrl);
ctrl->l3initiated = 0;
@@ -657,8 +668,6 @@ static void t200_expire(void *vpri)
start_t200(ctrl);
} else {
q921_discard_iqueue(ctrl);
//pri_error(ctrl, "MDL-ERROR (G) : T200 expired N200 times in state %d(%s)\n",
// ctrl->q921_state, q921_state2str(ctrl->q921_state));
q921_mdl_error(ctrl, 'G');
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
/* DL-RELEASE indication */
@@ -671,8 +680,6 @@ static void t200_expire(void *vpri)
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);
@@ -1281,8 +1288,6 @@ static pri_event * q921_sabme_rx(struct pri *ctrl, q921_h *h)
/* Send Unnumbered Acknowledgement */
q921_send_ua(ctrl, h->u.p_f);
q921_clear_exception_conditions(ctrl);
//pri_error(ctrl, "MDL-ERROR (F), SABME in state %d(%s)\n",
// ctrl->q921_state, q921_state2str(ctrl->q921_state));
q921_mdl_error(ctrl, 'F');
if (ctrl->v_s != ctrl->v_a) {
q921_discard_iqueue(ctrl);
@@ -1694,19 +1699,13 @@ static pri_event *q921_ua_rx(struct pri *ctrl, q921_h *h)
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 {
//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 (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;
}
@@ -1736,8 +1735,6 @@ static pri_event *q921_ua_rx(struct pri *ctrl, q921_h *h)
break;
case Q921_AWAITING_RELEASE:
if (!h->u.p_f) {
//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');
} else {
/* return DL-RELEASE-CONFIRM */
@@ -1804,7 +1801,6 @@ static int n_r_is_valid(struct pri *ctrl, int n_r)
for (x = ctrl->v_a; x != n_r && x != ctrl->v_s; Q921_INC(x)) {
}
if (x != n_r) {
/* MDL-ERROR (J): N(R) is not within ack window. */
return 0;
} else {
return 1;
@@ -1879,8 +1875,6 @@ static pri_event *q921_rr_rx(struct pri *ctrl, q921_h *h)
}
} else {
if (h->s.p_f) {
//pri_message(ctrl, "MDL-ERROR (A): Got RR response with p_f bit set to 1 in state %d(%s)\n",
// ctrl->q921_state, q921_state2str(ctrl->q921_state));
q921_mdl_error(ctrl, 'A');
}
}
@@ -1974,8 +1968,6 @@ static pri_event *q921_rej_rx(struct pri *ctrl, q921_h *h)
}
} else {
if (h->s.p_f) {
//pri_message(ctrl, "MDL-ERROR (A): Got REJ response with p_f bit set to 1 in state %d(%s)\n",
// ctrl->q921_state, q921_state2str(ctrl->q921_state));
q921_mdl_error(ctrl, 'A');
}
}
@@ -2165,7 +2157,6 @@ static pri_event *q921_dm_rx(struct pri *ctrl, q921_h *h)
break;
case Q921_MULTI_FRAME_ESTABLISHED:
if (h->u.p_f) {
/* MDL-ERROR (B) indication */
q921_mdl_error(ctrl, 'B');
break;
}
@@ -2177,10 +2168,8 @@ static pri_event *q921_dm_rx(struct pri *ctrl, q921_h *h)
break;
case Q921_TIMER_RECOVERY:
if (h->u.p_f) {
/* MDL-ERROR (B) indication */
q921_mdl_error(ctrl, 'B');
} else {
/* MDL-ERROR (E) indication */
q921_mdl_error(ctrl, 'E');
}
q921_establish_data_link(ctrl);
@@ -2209,7 +2198,6 @@ static pri_event *q921_rnr_rx(struct pri *ctrl, q921_h *h)
ctrl->peer_rx_busy = 1;
if (!is_command(ctrl, h)) {
if (h->s.p_f) {
/* MDL-ERROR (A) indication */
q921_mdl_error(ctrl, 'A');
}
} else {

143
q931.c
View File

@@ -4157,6 +4157,85 @@ static char *disc2str(int disc)
return code2str(disc, discs, sizeof(discs) / sizeof(discs[0]));
}
/*!
* \internal
* \brief Dump the Q.931 message header.
*
* \param ctrl D channel controller.
* \param tei TEI the packet is associated with.
* \param h Q.931 packet contents/header.
* \param len Received length of the Q.931 packet.
* \param c Message direction prefix character.
*
* \retval 0 on success.
* \retval -1 on error.
*/
static int q931_dump_header(struct pri *ctrl, int tei, q931_h *h, int len, char c)
{
q931_mh *mh;
int cref;
pri_message(ctrl, "%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
if (len < 2 || len < 2 + h->crlen) {
pri_message(ctrl, "%c Message too short for call reference. len=%d\n",
c, len);
return -1;
}
cref = q931_cr(h);
pri_message(ctrl, "%c TEI=%d Call Ref: len=%2d (reference %d/0x%X) (%s)\n",
c, tei, h->crlen, cref & ~Q931_CALL_REFERENCE_FLAG,
cref & ~Q931_CALL_REFERENCE_FLAG, (cref == Q931_DUMMY_CALL_REFERENCE)
? "Dummy"
: (cref & Q931_CALL_REFERENCE_FLAG)
? "Sent to originator" : "Sent from originator");
if (len < 3 + h->crlen) {
pri_message(ctrl, "%c Message too short for supported protocols. len=%d\n",
c, len);
return -1;
}
/* Message header begins at the end of the call reference number */
mh = (q931_mh *)(h->contents + h->crlen);
switch (h->pd) {
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_1:
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_2:
pri_message(ctrl, "%c Message Type: %s (%d)\n", c, maintenance_msg2str(mh->msg, h->pd), mh->msg);
break;
default:
/* Unknown protocol discriminator but we will treat it as Q.931 anyway. */
case GR303_PROTOCOL_DISCRIMINATOR:
case Q931_PROTOCOL_DISCRIMINATOR:
pri_message(ctrl, "%c Message Type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
break;
}
return 0;
}
/*!
* \internal
* \brief Q.931 is passing this message to Q.921 debug indication.
*
* \param ctrl D channel controller.
* \param tei TEI the packet is associated with.
* \param h Q.931 packet contents/header.
* \param len Received length of the Q.931 packet
*
* \return Nothing
*/
static void q931_to_q921_passing_dump(struct pri *ctrl, int tei, q931_h *h, int len)
{
char c;
c = '>';
pri_message(ctrl, "\n");
pri_message(ctrl, "%c DL-DATA request\n", c);
q931_dump_header(ctrl, tei, h, len, c);
}
/*!
* \brief Debug dump the given Q.931 packet.
*
@@ -4176,46 +4255,19 @@ void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx)
int r;
int cur_codeset;
int codeset;
int cref;
c = txrx ? '>' : '<';
pri_message(ctrl, "%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
if (len < 2 || len < 2 + h->crlen) {
pri_message(ctrl, "%c Message too short for call reference. len=%d\n",
c, len);
return;
if (!(ctrl->debug & (PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW))) {
/* Put out a blank line if Q.921 is not dumping. */
pri_message(ctrl, "\n");
}
cref = q931_cr(h);
pri_message(ctrl, "%c TEI=%d Call Ref: len=%2d (reference %d/0x%X) (%s)\n",
c, tei, h->crlen, cref & ~Q931_CALL_REFERENCE_FLAG,
cref & ~Q931_CALL_REFERENCE_FLAG, (cref == Q931_DUMMY_CALL_REFERENCE)
? "Dummy"
: (cref & Q931_CALL_REFERENCE_FLAG)
? "Sent to originator" : "Sent from originator");
if (len < 3 + h->crlen) {
pri_message(ctrl, "%c Message too short for supported protocols. len=%d\n",
c, len);
if (q931_dump_header(ctrl, tei, h, len, c)) {
return;
}
/* Message header begins at the end of the call reference number */
mh = (q931_mh *)(h->contents + h->crlen);
switch (h->pd) {
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_1:
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_2:
pri_message(ctrl, "%c Message Type: %s (%d)\n", c, maintenance_msg2str(mh->msg, h->pd), mh->msg);
break;
default:
/* Unknown protocol discriminator but we will treat it as Q.931 anyway. */
case GR303_PROTOCOL_DISCRIMINATOR:
case Q931_PROTOCOL_DISCRIMINATOR:
pri_message(ctrl, "%c Message Type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
break;
}
/* Drop length of header, including call reference */
mh = (q931_mh *)(h->contents + h->crlen);
len -= (h->crlen + 3);
codeset = cur_codeset = 0;
for (x = 0; x < len; x += r) {
@@ -4337,21 +4389,30 @@ static void init_header(struct pri *ctrl, q931_call *call, unsigned char *buf, q
static int q931_xmit(struct pri *ctrl, int tei, q931_h *h, int len, int cr, int uiframe)
{
/*
* Dump the Q.931 message first. Q.921 may have to request a TEI or
* bring the connection up before it can actually send the message.
* Therefore, the Q.931 message may actually get sent a few seconds
* later.
*/
if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
q931_dump(ctrl, tei, h, len, 1);
}
#ifdef LIBPRI_COUNTERS
ctrl->q931_txcount++;
#endif
if (uiframe) {
q921_transmit_uiframe(ctrl, h, len);
if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
/*
* The transmit operation might dump the Q.921 header, so logging
* the Q.931 message body after the transmit puts the sections of
* the message in the right order in the log,
*/
q931_dump(ctrl, tei, h, len, 1);
}
} else {
/*
* Indicate passing the Q.931 message to Q.921 first. Q.921 may
* have to request a TEI or bring the connection up before it can
* actually send the message. Therefore, the Q.931 message may
* actually get sent a few seconds later. Q.921 will dump the
* Q.931 message as appropriate at that time.
*/
if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
q931_to_q921_passing_dump(ctrl, tei, h, len);
}
q921_transmit_iframe(ctrl, tei, h, len, cr);
}
return 0;