Merge of Q.921 rewrite branch for wider testing.

git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1406 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
Matthew Fredrickson 2010-01-13 19:37:59 +00:00
parent 14f04072c8
commit 4d3bb14731
7 changed files with 1413 additions and 657 deletions

View File

@ -144,7 +144,7 @@ install: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
ifneq (${OSARCH},SunOS) ifneq (${OSARCH},SunOS)
install -m 644 libpri.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include install -m 644 libpri.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include
install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(libdir) install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY); fi #if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY); fi
( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf libpri.so.$(SONAME) libpri.so) ( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf libpri.so.$(SONAME) libpri.so)
install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(libdir) install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
if test $$(id -u) = 0; then $(LDCONFIG) $(LDCONFIG_FLAGS) $(INSTALL_PREFIX)$(libdir); fi if test $$(id -u) = 0; then $(LDCONFIG) $(LDCONFIG_FLAGS) $(INSTALL_PREFIX)$(libdir); fi

29
pri.c
View File

@ -144,7 +144,12 @@ static void pri_default_timers(struct pri *ctrl, int switchtype)
/* Set timer values to standard defaults. Time is in ms. */ /* Set timer values to standard defaults. Time is in ms. */
ctrl->timers[PRI_TIMER_N200] = 3; /* Max numer of Q.921 retransmissions */ ctrl->timers[PRI_TIMER_N200] = 3; /* Max numer of Q.921 retransmissions */
ctrl->timers[PRI_TIMER_N202] = 3; /* Max numer of transmissions of the TEI identity request message */ ctrl->timers[PRI_TIMER_N202] = 3; /* Max numer of transmissions of the TEI identity request message */
ctrl->timers[PRI_TIMER_K] = 7; /* Max number of outstanding I-frames */
if (ctrl->bri == 1)
ctrl->timers[PRI_TIMER_K] = 1; /* Max number of outstanding I-frames */
else
ctrl->timers[PRI_TIMER_K] = 7; /* Max number of outstanding I-frames */
ctrl->timers[PRI_TIMER_T200] = 1000; /* Time between SABME's */ ctrl->timers[PRI_TIMER_T200] = 1000; /* Time between SABME's */
ctrl->timers[PRI_TIMER_T202] = 10 * 1000; /* Min time between transmission of TEI Identity request messages */ ctrl->timers[PRI_TIMER_T202] = 10 * 1000; /* Min time between transmission of TEI Identity request messages */
ctrl->timers[PRI_TIMER_T203] = 10 * 1000; /* Max time without exchanging packets */ ctrl->timers[PRI_TIMER_T203] = 10 * 1000; /* Max time without exchanging packets */
@ -154,6 +159,7 @@ static void pri_default_timers(struct pri *ctrl, int switchtype)
ctrl->timers[PRI_TIMER_TM20] = 2500; /* Max time awaiting XID response - Q.921 Appendix IV */ ctrl->timers[PRI_TIMER_TM20] = 2500; /* Max time awaiting XID response - Q.921 Appendix IV */
ctrl->timers[PRI_TIMER_NM20] = 3; /* Number of XID retransmits - Q.921 Appendix IV */ ctrl->timers[PRI_TIMER_NM20] = 3; /* Number of XID retransmits - Q.921 Appendix IV */
ctrl->timers[PRI_TIMER_T303] = 4 * 1000; /* Length between SETUP retransmissions and timeout */ ctrl->timers[PRI_TIMER_T303] = 4 * 1000; /* Length between SETUP retransmissions and timeout */
ctrl->timers[PRI_TIMER_T309] = 6000; /* Time to wait before clearing calls in case of D-channel transient event. Q.931 specifies 6-90 seconds */
ctrl->timers[PRI_TIMER_T_HOLD] = 4 * 1000; /* Wait for HOLD request response. */ ctrl->timers[PRI_TIMER_T_HOLD] = 4 * 1000; /* Wait for HOLD request response. */
ctrl->timers[PRI_TIMER_T_RETRIEVE] = 4 * 1000;/* Wait for RETRIEVE request response. */ ctrl->timers[PRI_TIMER_T_RETRIEVE] = 4 * 1000;/* Wait for RETRIEVE request response. */
@ -343,9 +349,16 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
default: default:
break; break;
} }
/* Start Q.921 layer, Wait if we're the network */ p->k = p->timers[PRI_TIMER_K];
if (p)
q921_start(p, p->localtype == PRI_CPE); if (p->tei == Q921_TEI_GROUP && p->sapi == Q921_SAPI_LAYER2_MANAGEMENT && p->localtype == PRI_CPE) {
p->subchannel = __pri_new_tei(-1, p->localtype, p->switchtype, p, NULL, NULL, NULL, Q921_TEI_PRI, 1);
if (!p->subchannel) {
free(p);
return NULL;
}
} else
q921_start(p);
return p; return p;
} }
@ -363,11 +376,15 @@ void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars)
int pri_restart(struct pri *pri) int pri_restart(struct pri *pri)
{ {
#if 0
/* Restart Q.921 layer */ /* Restart Q.921 layer */
if (pri) { if (pri) {
q921_reset(pri, 1); q921_reset(pri, 1);
q921_start(pri, pri->localtype == PRI_CPE); q921_start(pri, pri->localtype == PRI_CPE);
} }
#else
pri_error(pri, "pri_restart should never be called !!!!\n");
#endif
return 0; return 0;
} }
@ -1303,12 +1320,14 @@ char *pri_dump_info_str(struct pri *ctrl)
} }
used = pri_snprintf(buf, used, buf_size, "Q921 Outstanding: %u\n", q921outstanding); used = pri_snprintf(buf, used, buf_size, "Q921 Outstanding: %u\n", q921outstanding);
#endif #endif
used = pri_snprintf(buf, used, buf_size, "Window Length: %d/%d\n", ctrl->windowlen, #if 0
used = pri_snprintf(buf, used, buf_size, "Window Length: %d/%d\n", ctrl->k,
ctrl->window); ctrl->window);
used = pri_snprintf(buf, used, buf_size, "Sentrej: %d\n", ctrl->sentrej); used = pri_snprintf(buf, used, buf_size, "Sentrej: %d\n", ctrl->sentrej);
used = pri_snprintf(buf, used, buf_size, "SolicitFbit: %d\n", ctrl->solicitfbit); used = pri_snprintf(buf, used, buf_size, "SolicitFbit: %d\n", ctrl->solicitfbit);
used = pri_snprintf(buf, used, buf_size, "Retrans: %d\n", ctrl->retrans); used = pri_snprintf(buf, used, buf_size, "Retrans: %d\n", ctrl->retrans);
used = pri_snprintf(buf, used, buf_size, "Busy: %d\n", ctrl->busy); used = pri_snprintf(buf, used, buf_size, "Busy: %d\n", ctrl->busy);
#endif
used = pri_snprintf(buf, used, buf_size, "Overlap Dial: %d\n", ctrl->overlapdial); used = pri_snprintf(buf, used, buf_size, "Overlap Dial: %d\n", ctrl->overlapdial);
used = pri_snprintf(buf, used, buf_size, "Logical Channel Mapping: %d\n", used = pri_snprintf(buf, used, buf_size, "Logical Channel Mapping: %d\n",
ctrl->chan_mapping_logical); ctrl->chan_mapping_logical);

View File

@ -89,25 +89,30 @@ struct pri {
unsigned int hold_support:1;/* TRUE if upper layer supports call hold. */ unsigned int hold_support:1;/* TRUE if upper layer supports call hold. */
unsigned int deflection_support:1;/* TRUE if upper layer supports call deflection/rerouting. */ unsigned int deflection_support:1;/* TRUE if upper layer supports call deflection/rerouting. */
/* MDL variables */
int mdl_error;
int mdl_error_state;
int mdl_timer;
int mdl_free_me;
/* Q.921 State */ /* Q.921 State */
int q921_state; int q921_state;
int window; /* Max window size */ int k;
int windowlen; /* Fullness of window */ int RC;
int peer_rx_busy:1;
int own_rx_busy:1;
int acknowledge_pending:1;
int reject_exception:1;
int v_s; /* Next N(S) for transmission */ int v_s; /* Next N(S) for transmission */
int v_a; /* Last acknowledged frame */ int v_a; /* Last acknowledged frame */
int v_r; /* Next frame expected to be received */ int v_r; /* Next frame expected to be received */
int v_na; /* What we've told our peer we've acknowledged */
int solicitfbit; /* Have we sent an I or S frame with the F-bit set? */
int retrans; /* Retransmissions */
int sentrej; /* Are we in reject state */
int cref; /* Next call reference value */ int cref; /* Next call reference value */
int busy; /* Peer is busy */ int l3initiated;
/* Various timers */ /* Various timers */
int sabme_timer; /* SABME retransmit */
int sabme_count; /* SABME retransmit counter for BRI */
int t203_timer; /* Max idle time */ int t203_timer; /* Max idle time */
int t202_timer; int t202_timer;
int n202_counter; int n202_counter;
@ -515,6 +520,8 @@ struct q931_call {
-1 - No reverse charging -1 - No reverse charging
1 - Reverse charging 1 - Reverse charging
0,2-7 - Reserved for future use */ 0,2-7 - Reserved for future use */
/*! \brief TEI associated with call */
int tei;
int t303_timer; int t303_timer;
int t303_expirycnt; int t303_expirycnt;
@ -627,13 +634,40 @@ static inline int BRI_TE_PTMP(struct pri *mypri)
return pri->bri && (((pri)->localtype == PRI_CPE) && ((pri)->tei == Q921_TEI_GROUP)); return pri->bri && (((pri)->localtype == PRI_CPE) && ((pri)->tei == Q921_TEI_GROUP));
} }
static inline int PRI_PTP(struct pri *mypri) static inline int NT_MODE(struct pri *mypri)
{ {
struct pri *pri; struct pri *pri;
pri = PRI_MASTER(mypri); pri = PRI_MASTER(mypri);
return !pri->bri; return pri->localtype == PRI_NETWORK;
}
static inline int TE_MODE(struct pri *mypri)
{
struct pri *pri;
pri = PRI_MASTER(mypri);
return pri->localtype == PRI_CPE;
}
static inline int PTP_MODE(struct pri *mypri)
{
struct pri *pri;
pri = PRI_MASTER(mypri);
return pri->tei == Q921_TEI_PRI;
}
static inline int PTMP_MODE(struct pri *mypri)
{
struct pri *pri;
pri = PRI_MASTER(mypri);
return pri->tei == Q921_TEI_GROUP;
} }
#define Q931_DUMMY_CALL_REFERENCE -1 #define Q931_DUMMY_CALL_REFERENCE -1

View File

@ -166,36 +166,41 @@ typedef struct q921_frame {
} q921_frame; } q921_frame;
#define Q921_INC(j) (j) = (((j) + 1) % 128) #define Q921_INC(j) (j) = (((j) + 1) % 128)
#define Q921_DEC(j) (j) = (((j) - 1) % 128)
typedef enum q921_state { typedef enum q921_state {
Q921_DOWN = 0, /* All states except Q921_DOWN are defined in Q.921 SDL diagrams */
Q921_TEI_UNASSIGNED, Q921_TEI_UNASSIGNED = 1,
Q921_TEI_AWAITING_ESTABLISH, Q921_ASSIGN_AWAITING_TEI = 2,
Q921_TEI_AWAITING_ASSIGN, Q921_ESTABLISH_AWAITING_TEI = 3,
Q921_TEI_ASSIGNED, Q921_TEI_ASSIGNED = 4,
Q921_NEGOTIATION, Q921_AWAITING_ESTABLISHMENT = 5,
Q921_LINK_CONNECTION_RELEASED, /* Also known as TEI_ASSIGNED */ Q921_AWAITING_RELEASE = 6,
Q921_LINK_CONNECTION_ESTABLISHED, Q921_MULTI_FRAME_ESTABLISHED = 7,
Q921_AWAITING_ESTABLISH, Q921_TIMER_RECOVERY = 8,
Q921_AWAITING_RELEASE
} q921_state; } q921_state;
static inline int Q921_ADD(int a, int b)
{
return (a + b) % 128;
}
/* Dumps a *known good* Q.921 packet */ /* Dumps a *known good* Q.921 packet */
extern void q921_dump(struct pri *pri, q921_h *h, int len, int showraw, int txrx); extern void q921_dump(struct pri *pri, q921_h *h, int len, int showraw, int txrx);
/* Bring up the D-channel */ /* Bring up the D-channel */
extern void q921_start(struct pri *pri, int now); extern void q921_start(struct pri *pri);
extern void q921_reset(struct pri *pri, int reset_iqueue); //extern void q921_reset(struct pri *pri, int reset_iqueue);
extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len); 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 int q921_transmit_iframe(struct pri *pri, int tei, void *buf, int len, int cr);
extern int q921_transmit_uiframe(struct pri *pri, void *buf, int len); extern int q921_transmit_uiframe(struct pri *pri, void *buf, int len);
extern pri_event *q921_dchannel_up(struct pri *pri); extern pri_event *q921_dchannel_up(struct pri *pri);
extern pri_event *q921_dchannel_down(struct pri *pri); //extern pri_event *q921_dchannel_down(struct pri *pri);
#endif #endif

View File

@ -452,7 +452,7 @@ extern int maintenance_service_ack(struct pri *pri, q931_call *call);
/* Q.SIG specific */ /* Q.SIG specific */
#define QSIG_IE_TRANSIT_COUNT 0x31 #define QSIG_IE_TRANSIT_COUNT 0x31
extern int q931_receive(struct pri *pri, q931_h *h, int len); extern int q931_receive(struct pri *pri, int tei, q931_h *h, int len);
extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info); extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);

1922
q921.c

File diff suppressed because it is too large Load Diff

26
q931.c
View File

@ -3926,12 +3926,12 @@ static void init_header(struct pri *ctrl, q931_call *call, unsigned char *buf, q
*mhb = mh; *mhb = mh;
} }
static int q931_xmit(struct pri *ctrl, q931_h *h, int len, int cr, int uiframe) static int q931_xmit(struct pri *ctrl, int tei, q931_h *h, int len, int cr, int uiframe)
{ {
if (uiframe) { if (uiframe) {
q921_transmit_uiframe(ctrl, h, len); q921_transmit_uiframe(ctrl, h, len);
} else { } else {
q921_transmit_iframe(ctrl, h, len, cr); q921_transmit_iframe(ctrl, tei, h, len, cr);
} }
/* The transmit operation might dump the q921 header, so logging the q931 /* The transmit operation might dump the q921 header, so logging the q931
message body after the transmit puts the sections of the message in the message body after the transmit puts the sections of the message in the
@ -3998,14 +3998,6 @@ static int send_message(struct pri *ctrl, q931_call *call, int msgtype, int ies[
len = sizeof(buf) - len; len = sizeof(buf) - len;
ctrl = call->pri; ctrl = call->pri;
if (BRI_TE_PTMP(ctrl)) {
/*
* Must use the BRI subchannel structure to send with the correct TEI.
* Note: If the subchannel is NULL then there is no TEI assigned and
* we should not be sending anything out at this time.
*/
ctrl = ctrl->subchannel;
}
if (ctrl) { if (ctrl) {
int uiframe; int uiframe;
@ -4054,7 +4046,7 @@ static int send_message(struct pri *ctrl, q931_call *call, int msgtype, int ies[
ctrl, ctrl->tei, ctrl->sapi, ctrl, ctrl->tei, ctrl->sapi,
call->pri, call->pri->tei, call->pri->sapi); call->pri, call->pri->tei, call->pri->sapi);
} }
q931_xmit(ctrl, h, len, 1, uiframe); q931_xmit(ctrl, ctrl->tei, h, len, 1, uiframe);
} }
call->acked = 1; call->acked = 1;
return 0; return 0;
@ -5776,7 +5768,7 @@ static struct q931_call *q931_get_subcall(struct pri *ctrl, struct q931_call *ma
return cur; return cur;
} }
int q931_receive(struct pri *ctrl, q931_h *h, int len) int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
{ {
q931_mh *mh; q931_mh *mh;
q931_call *c; q931_call *c;
@ -5810,7 +5802,7 @@ int q931_receive(struct pri *ctrl, q931_h *h, int len)
KLUDGE this by changing byte 4 from a 0xf (SERVICE) KLUDGE this by changing byte 4 from a 0xf (SERVICE)
to a 0x7 (SERVICE ACKNOWLEDGE) */ to a 0x7 (SERVICE ACKNOWLEDGE) */
h->raw[h->crlen + 2] -= 0x8; h->raw[h->crlen + 2] -= 0x8;
q931_xmit(ctrl, h, len, 1, 0); q931_xmit(ctrl, ctrl->tei, h, len, 1, 0);
return 0; return 0;
} }
@ -5973,11 +5965,11 @@ static int post_handle_maintenance_message(struct pri *ctrl, int protodisc, stru
switch (0x0f & c->changestatus) { switch (0x0f & c->changestatus) {
case SERVICE_CHANGE_STATUS_INSERVICE: case SERVICE_CHANGE_STATUS_INSERVICE:
ctrl->ev.e = PRI_EVENT_DCHAN_UP; ctrl->ev.e = PRI_EVENT_DCHAN_UP;
q921_dchannel_up(ctrl); //q921_dchannel_up(ctrl);
break; break;
case SERVICE_CHANGE_STATUS_OUTOFSERVICE: case SERVICE_CHANGE_STATUS_OUTOFSERVICE:
ctrl->ev.e = PRI_EVENT_DCHAN_DOWN; ctrl->ev.e = PRI_EVENT_DCHAN_DOWN;
q921_dchannel_down(ctrl); //q921_dchannel_down(ctrl);
break; break;
default: default:
pri_error(ctrl, "!! Don't know how to handle span service change status '%d'\n", (0x0f & c->changestatus)); pri_error(ctrl, "!! Don't know how to handle span service change status '%d'\n", (0x0f & c->changestatus));
@ -5997,11 +5989,11 @@ static int post_handle_maintenance_message(struct pri *ctrl, int protodisc, stru
switch (0x0f & c->changestatus) { switch (0x0f & c->changestatus) {
case SERVICE_CHANGE_STATUS_INSERVICE: case SERVICE_CHANGE_STATUS_INSERVICE:
ctrl->ev.e = PRI_EVENT_DCHAN_UP; ctrl->ev.e = PRI_EVENT_DCHAN_UP;
q921_dchannel_up(ctrl); //q921_dchannel_up(ctrl);
break; break;
case SERVICE_CHANGE_STATUS_OUTOFSERVICE: case SERVICE_CHANGE_STATUS_OUTOFSERVICE:
ctrl->ev.e = PRI_EVENT_DCHAN_DOWN; ctrl->ev.e = PRI_EVENT_DCHAN_DOWN;
q921_dchannel_down(ctrl); //q921_dchannel_down(ctrl);
break; break;
default: default:
pri_error(ctrl, "!! Don't know how to handle span service change status '%d'\n", (0x0f & c->changestatus)); pri_error(ctrl, "!! Don't know how to handle span service change status '%d'\n", (0x0f & c->changestatus));