Asterisk is getting a "No D-channels available!" warning message every 4 seconds.
For PTP links, libpri generated the PRI_EVENT_DCHAN_DOWN event every time it failed to bring layer 2 up because the physical layer is down. For PTP links, made generate the PRI_EVENT_DCHAN_UP/PRI_EVENT_DCHAN_DOWN only when it enters/exits the Q.921 superstate consisting of states 7(Q921_MULTI_FRAME_ESTABLISHED) and 8(Q921_TIMER_RECOVERY). Also changed the PTP link restart delay to be link specific instead of D channel specific because the GR-303 PTP switch types have more than one Q.921 link. (closes issue #17270) Reported by: jmls git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2113 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
parent
12805eb71f
commit
517e5ac5ce
@ -119,8 +119,6 @@ struct pri {
|
|||||||
int t201_timer;
|
int t201_timer;
|
||||||
/*! Number of times T201 has expired. */
|
/*! Number of times T201 has expired. */
|
||||||
int t201_expirycnt;
|
int t201_expirycnt;
|
||||||
/*! PTP layer 2 restart delay timer */
|
|
||||||
int restart_timer;
|
|
||||||
|
|
||||||
int cref; /* Next call reference value */
|
int cref; /* Next call reference value */
|
||||||
|
|
||||||
|
@ -246,6 +246,8 @@ struct q921_link {
|
|||||||
int n202_counter;
|
int n202_counter;
|
||||||
/*! Max idle time */
|
/*! Max idle time */
|
||||||
int t203_timer;
|
int t203_timer;
|
||||||
|
/*! PTP restart delay timer */
|
||||||
|
int restart_timer;
|
||||||
|
|
||||||
/* MDL variables */
|
/* MDL variables */
|
||||||
int mdl_timer;
|
int mdl_timer;
|
||||||
|
105
q921.c
105
q921.c
@ -548,17 +548,18 @@ static void stop_t200(struct q921_link *link)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restart_timer_expire(void *vctrl)
|
static void restart_timer_expire(void *vlink)
|
||||||
{
|
{
|
||||||
struct pri *ctrl = vctrl;
|
struct q921_link *link = vlink;
|
||||||
struct q921_link *link;
|
struct pri *ctrl;
|
||||||
|
|
||||||
|
ctrl = link->ctrl;
|
||||||
|
|
||||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||||
pri_message(ctrl, "Kick starting layer 2\n");
|
pri_message(ctrl, "SAPI/TEI=%d/%d Kick starting link\n", link->sapi, link->tei);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrl->restart_timer = 0;
|
link->restart_timer = 0;
|
||||||
link = &ctrl->link;
|
|
||||||
|
|
||||||
switch (link->state) {
|
switch (link->state) {
|
||||||
case Q921_TEI_ASSIGNED:
|
case Q921_TEI_ASSIGNED:
|
||||||
@ -570,31 +571,42 @@ static void restart_timer_expire(void *vctrl)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Looks like someone forgot to stop the restart timer. */
|
/* Looks like someone forgot to stop the restart timer. */
|
||||||
pri_error(ctrl, "Layer 2 restart delay timer expired in state %d(%s)\n",
|
pri_error(ctrl, "SAPI/TEI=%d/%d Link restart delay timer expired in state %d(%s)\n",
|
||||||
link->state, q921_state2str(link->state));
|
link->sapi, link->tei, link->state, q921_state2str(link->state));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restart_timer_stop(struct pri *ctrl)
|
static void restart_timer_stop(struct q921_link *link)
|
||||||
{
|
{
|
||||||
pri_schedule_del(ctrl, ctrl->restart_timer);
|
struct pri *ctrl;
|
||||||
ctrl->restart_timer = 0;
|
|
||||||
|
ctrl = link->ctrl;
|
||||||
|
pri_schedule_del(ctrl, link->restart_timer);
|
||||||
|
link->restart_timer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restart_timer_start(struct pri *ctrl)
|
static void restart_timer_start(struct q921_link *link)
|
||||||
{
|
{
|
||||||
|
struct pri *ctrl;
|
||||||
|
|
||||||
|
ctrl = link->ctrl;
|
||||||
|
|
||||||
if (ctrl->debug & PRI_DEBUG_Q921_DUMP) {
|
if (ctrl->debug & PRI_DEBUG_Q921_DUMP) {
|
||||||
pri_message(ctrl, "-- Starting layer 2 restart delay timer\n");
|
pri_message(ctrl, "SAPI/TEI=%d/%d Starting link restart delay timer\n",
|
||||||
|
link->sapi, link->tei);
|
||||||
}
|
}
|
||||||
pri_schedule_del(ctrl, ctrl->restart_timer);
|
pri_schedule_del(ctrl, link->restart_timer);
|
||||||
ctrl->restart_timer =
|
link->restart_timer =
|
||||||
pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T200], restart_timer_expire, ctrl);
|
pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T200], restart_timer_expire, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pri_event *q921_ptp_delay_restart(struct pri *ctrl)
|
static pri_event *q921_ptp_delay_restart(struct q921_link *link)
|
||||||
{
|
{
|
||||||
pri_event *ev;
|
pri_event *ev;
|
||||||
|
struct pri *ctrl;
|
||||||
|
|
||||||
|
ctrl = link->ctrl;
|
||||||
|
|
||||||
if (PTP_MODE(ctrl)) {
|
if (PTP_MODE(ctrl)) {
|
||||||
/*
|
/*
|
||||||
@ -602,12 +614,20 @@ static pri_event *q921_ptp_delay_restart(struct pri *ctrl)
|
|||||||
* got an L3 that depends on us keeping L2 automatically alive
|
* got an L3 that depends on us keeping L2 automatically alive
|
||||||
* and happy for PTP links.
|
* and happy for PTP links.
|
||||||
*/
|
*/
|
||||||
restart_timer_start(ctrl);
|
restart_timer_start(link);
|
||||||
|
|
||||||
/* Notify the upper layer that layer 2 is down. */
|
switch (link->state) {
|
||||||
|
case Q921_MULTI_FRAME_ESTABLISHED:
|
||||||
|
case Q921_TIMER_RECOVERY:
|
||||||
|
/* Notify the upper layer that layer 2 went down. */
|
||||||
ctrl->schedev = 1;
|
ctrl->schedev = 1;
|
||||||
ctrl->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
|
ctrl->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
|
||||||
ev = &ctrl->ev;
|
ev = &ctrl->ev;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ev = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ev = NULL;
|
ev = NULL;
|
||||||
}
|
}
|
||||||
@ -817,6 +837,10 @@ static void t200_expire(void *vlink)
|
|||||||
q921_establish_data_link(link);
|
q921_establish_data_link(link);
|
||||||
link->l3_initiated = 0;
|
link->l3_initiated = 0;
|
||||||
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
||||||
|
if (PTP_MODE(ctrl)) {
|
||||||
|
ctrl->schedev = 1;
|
||||||
|
ctrl->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Q921_AWAITING_ESTABLISHMENT:
|
case Q921_AWAITING_ESTABLISHMENT:
|
||||||
@ -825,12 +849,12 @@ static void t200_expire(void *vlink)
|
|||||||
q921_send_sabme(link);
|
q921_send_sabme(link);
|
||||||
start_t200(link);
|
start_t200(link);
|
||||||
} else {
|
} else {
|
||||||
|
q921_ptp_delay_restart(link);
|
||||||
q921_discard_iqueue(link);
|
q921_discard_iqueue(link);
|
||||||
q921_mdl_error(link, 'G');
|
q921_mdl_error(link, 'G');
|
||||||
q921_setstate(link, Q921_TEI_ASSIGNED);
|
q921_setstate(link, Q921_TEI_ASSIGNED);
|
||||||
/* DL-RELEASE indication */
|
/* DL-RELEASE indication */
|
||||||
q931_dl_event(link, Q931_DL_EVENT_DL_RELEASE_IND);
|
q931_dl_event(link, Q931_DL_EVENT_DL_RELEASE_IND);
|
||||||
q921_ptp_delay_restart(ctrl);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Q921_AWAITING_RELEASE:
|
case Q921_AWAITING_RELEASE:
|
||||||
@ -839,11 +863,11 @@ static void t200_expire(void *vlink)
|
|||||||
q921_send_disc(link, 1);
|
q921_send_disc(link, 1);
|
||||||
start_t200(link);
|
start_t200(link);
|
||||||
} else {
|
} else {
|
||||||
|
q921_ptp_delay_restart(link);
|
||||||
q921_mdl_error(link, 'H');
|
q921_mdl_error(link, 'H');
|
||||||
/* DL-RELEASE confirm */
|
/* DL-RELEASE confirm */
|
||||||
q931_dl_event(link, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
|
q931_dl_event(link, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
|
||||||
q921_setstate(link, Q921_TEI_ASSIGNED);
|
q921_setstate(link, Q921_TEI_ASSIGNED);
|
||||||
q921_ptp_delay_restart(ctrl);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -943,7 +967,7 @@ int q921_transmit_iframe(struct q921_link *link, void *buf, int len, int cr)
|
|||||||
switch (link->state) {
|
switch (link->state) {
|
||||||
case Q921_TEI_ASSIGNED:
|
case Q921_TEI_ASSIGNED:
|
||||||
/* If we aren't in a state compatiable with DL-DATA requests, start getting us there here */
|
/* If we aren't in a state compatiable with DL-DATA requests, start getting us there here */
|
||||||
restart_timer_stop(ctrl);
|
restart_timer_stop(link);
|
||||||
q921_establish_data_link(link);
|
q921_establish_data_link(link);
|
||||||
link->l3_initiated = 1;
|
link->l3_initiated = 1;
|
||||||
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
||||||
@ -1666,7 +1690,7 @@ static pri_event *q921_sabme_rx(struct q921_link *link, q921_h *h)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Q921_TEI_ASSIGNED:
|
case Q921_TEI_ASSIGNED:
|
||||||
restart_timer_stop(ctrl);
|
restart_timer_stop(link);
|
||||||
q921_send_ua(link, h->u.p_f);
|
q921_send_ua(link, h->u.p_f);
|
||||||
q921_clear_exception_conditions(link);
|
q921_clear_exception_conditions(link);
|
||||||
link->v_s = link->v_a = link->v_r = 0;
|
link->v_s = link->v_a = link->v_r = 0;
|
||||||
@ -1719,6 +1743,7 @@ static pri_event *q921_disc_rx(struct q921_link *link, q921_h *h)
|
|||||||
break;
|
break;
|
||||||
case Q921_MULTI_FRAME_ESTABLISHED:
|
case Q921_MULTI_FRAME_ESTABLISHED:
|
||||||
case Q921_TIMER_RECOVERY:
|
case Q921_TIMER_RECOVERY:
|
||||||
|
res = q921_ptp_delay_restart(link);
|
||||||
q921_discard_iqueue(link);
|
q921_discard_iqueue(link);
|
||||||
q921_send_ua(link, h->u.p_f);
|
q921_send_ua(link, h->u.p_f);
|
||||||
/* DL-RELEASE indication */
|
/* DL-RELEASE indication */
|
||||||
@ -1727,7 +1752,6 @@ static pri_event *q921_disc_rx(struct q921_link *link, q921_h *h)
|
|||||||
if (link->state == Q921_MULTI_FRAME_ESTABLISHED)
|
if (link->state == Q921_MULTI_FRAME_ESTABLISHED)
|
||||||
stop_t203(link);
|
stop_t203(link);
|
||||||
q921_setstate(link, Q921_TEI_ASSIGNED);
|
q921_setstate(link, Q921_TEI_ASSIGNED);
|
||||||
res = q921_ptp_delay_restart(ctrl);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pri_error(ctrl, "Don't know what to do with DISC in state %d(%s)\n",
|
pri_error(ctrl, "Don't know what to do with DISC in state %d(%s)\n",
|
||||||
@ -1760,7 +1784,7 @@ static void q921_mdl_remove(struct q921_link *link)
|
|||||||
|
|
||||||
switch (link->state) {
|
switch (link->state) {
|
||||||
case Q921_TEI_ASSIGNED:
|
case Q921_TEI_ASSIGNED:
|
||||||
restart_timer_stop(ctrl);
|
restart_timer_stop(link);
|
||||||
/* XXX: deviation! Since we don't have a UI queue, we just discard our I-queue */
|
/* XXX: deviation! Since we don't have a UI queue, we just discard our I-queue */
|
||||||
q921_discard_iqueue(link);
|
q921_discard_iqueue(link);
|
||||||
q921_setstate(link, Q921_TEI_UNASSIGNED);
|
q921_setstate(link, Q921_TEI_UNASSIGNED);
|
||||||
@ -1906,6 +1930,16 @@ static void q921_mdl_handle_ptp_error(struct q921_link *link, char error)
|
|||||||
ctrl = link->ctrl;
|
ctrl = link->ctrl;
|
||||||
|
|
||||||
switch (error) {
|
switch (error) {
|
||||||
|
case 'J':
|
||||||
|
/*
|
||||||
|
* This is for the transition to Q921_AWAITING_ESTABLISHMENT.
|
||||||
|
* The event is genereated here rather than where the MDL_ERROR
|
||||||
|
* 'J' is posted because of the potential event conflict with
|
||||||
|
* incoming I-frame information passed to Q.931.
|
||||||
|
*/
|
||||||
|
ctrl->schedev = 1;
|
||||||
|
ctrl->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
|
||||||
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
case 'B':
|
case 'B':
|
||||||
case 'C':
|
case 'C':
|
||||||
@ -1915,7 +1949,6 @@ static void q921_mdl_handle_ptp_error(struct q921_link *link, char error)
|
|||||||
case 'G':
|
case 'G':
|
||||||
case 'H':
|
case 'H':
|
||||||
case 'I':
|
case 'I':
|
||||||
case 'J':
|
|
||||||
case 'K':
|
case 'K':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2122,11 +2155,11 @@ static pri_event *q921_ua_rx(struct q921_link *link, q921_h *h)
|
|||||||
if (!h->u.p_f) {
|
if (!h->u.p_f) {
|
||||||
q921_mdl_error(link, 'D');
|
q921_mdl_error(link, 'D');
|
||||||
} else {
|
} else {
|
||||||
|
res = q921_ptp_delay_restart(link);
|
||||||
/* DL-RELEASE confirm */
|
/* DL-RELEASE confirm */
|
||||||
q931_dl_event(link, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
|
q931_dl_event(link, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
|
||||||
stop_t200(link);
|
stop_t200(link);
|
||||||
q921_setstate(link, Q921_TEI_ASSIGNED);
|
q921_setstate(link, Q921_TEI_ASSIGNED);
|
||||||
res = q921_ptp_delay_restart(ctrl);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2423,6 +2456,10 @@ static pri_event *q921_frmr_rx(struct q921_link *link, q921_h *h)
|
|||||||
q921_establish_data_link(link);
|
q921_establish_data_link(link);
|
||||||
link->l3_initiated = 0;
|
link->l3_initiated = 0;
|
||||||
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
||||||
|
if (PTP_MODE(ctrl)) {
|
||||||
|
ctrl->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
|
||||||
|
res = &ctrl->ev;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Q921_TEI_ASSIGNED:
|
case Q921_TEI_ASSIGNED:
|
||||||
case Q921_AWAITING_ESTABLISHMENT:
|
case Q921_AWAITING_ESTABLISHMENT:
|
||||||
@ -2558,7 +2595,7 @@ static pri_event *q921_dm_rx(struct q921_link *link, q921_h *h)
|
|||||||
if (h->u.p_f)
|
if (h->u.p_f)
|
||||||
break;
|
break;
|
||||||
/* else */
|
/* else */
|
||||||
restart_timer_stop(ctrl);
|
restart_timer_stop(link);
|
||||||
q921_establish_data_link(link);
|
q921_establish_data_link(link);
|
||||||
link->l3_initiated = 1;
|
link->l3_initiated = 1;
|
||||||
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
||||||
@ -2567,21 +2604,21 @@ static pri_event *q921_dm_rx(struct q921_link *link, q921_h *h)
|
|||||||
if (!h->u.p_f)
|
if (!h->u.p_f)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
res = q921_ptp_delay_restart(link);
|
||||||
q921_discard_iqueue(link);
|
q921_discard_iqueue(link);
|
||||||
/* DL-RELEASE indication */
|
/* DL-RELEASE indication */
|
||||||
q931_dl_event(link, Q931_DL_EVENT_DL_RELEASE_IND);
|
q931_dl_event(link, Q931_DL_EVENT_DL_RELEASE_IND);
|
||||||
stop_t200(link);
|
stop_t200(link);
|
||||||
q921_setstate(link, Q921_TEI_ASSIGNED);
|
q921_setstate(link, Q921_TEI_ASSIGNED);
|
||||||
res = q921_ptp_delay_restart(ctrl);
|
|
||||||
break;
|
break;
|
||||||
case Q921_AWAITING_RELEASE:
|
case Q921_AWAITING_RELEASE:
|
||||||
if (!h->u.p_f)
|
if (!h->u.p_f)
|
||||||
break;
|
break;
|
||||||
|
res = q921_ptp_delay_restart(link);
|
||||||
/* DL-RELEASE confirm */
|
/* DL-RELEASE confirm */
|
||||||
q931_dl_event(link, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
|
q931_dl_event(link, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
|
||||||
stop_t200(link);
|
stop_t200(link);
|
||||||
q921_setstate(link, Q921_TEI_ASSIGNED);
|
q921_setstate(link, Q921_TEI_ASSIGNED);
|
||||||
res = q921_ptp_delay_restart(ctrl);
|
|
||||||
break;
|
break;
|
||||||
case Q921_MULTI_FRAME_ESTABLISHED:
|
case Q921_MULTI_FRAME_ESTABLISHED:
|
||||||
if (h->u.p_f) {
|
if (h->u.p_f) {
|
||||||
@ -2593,6 +2630,10 @@ static pri_event *q921_dm_rx(struct q921_link *link, q921_h *h)
|
|||||||
q921_establish_data_link(link);
|
q921_establish_data_link(link);
|
||||||
link->l3_initiated = 0;
|
link->l3_initiated = 0;
|
||||||
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
||||||
|
if (PTP_MODE(ctrl)) {
|
||||||
|
ctrl->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
|
||||||
|
res = &ctrl->ev;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Q921_TIMER_RECOVERY:
|
case Q921_TIMER_RECOVERY:
|
||||||
if (h->u.p_f) {
|
if (h->u.p_f) {
|
||||||
@ -2603,6 +2644,10 @@ static pri_event *q921_dm_rx(struct q921_link *link, q921_h *h)
|
|||||||
q921_establish_data_link(link);
|
q921_establish_data_link(link);
|
||||||
link->l3_initiated = 0;
|
link->l3_initiated = 0;
|
||||||
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
q921_setstate(link, Q921_AWAITING_ESTABLISHMENT);
|
||||||
|
if (PTP_MODE(ctrl)) {
|
||||||
|
ctrl->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
|
||||||
|
res = &ctrl->ev;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pri_error(ctrl, "Don't know what to do with DM frame in state %d(%s)\n",
|
pri_error(ctrl, "Don't know what to do with DM frame in state %d(%s)\n",
|
||||||
|
Loading…
Reference in New Issue
Block a user