📄 mtp.c
字号:
abort_initial_alignment(m);
/* ToDo: Abort the entire initial alingment, if proving is aborted for
the fifth time. */
}
}
}
static void mtp2_bad_frame(mtp2_t *m, char* msg) {
char buf[3 * sizeof(m->backbuf) + 1];
int i;
struct timeval now;
static struct timeval last = {0, 0};
static int badcount = 0;
gettimeofday(&now, NULL);
if (last.tv_sec) {
int tdiff = (now.tv_sec - last.tv_sec) * 1000000 + (now.tv_usec - last.tv_usec);
if (tdiff < 10*1000000 && badcount < 10000) {
badcount++;
return;
}
else {
if (badcount) {
fifo_log(m, LOG_DEBUG, "Suppressed %d bad frame debug log messages on link '%s'\n", badcount, m->name);
badcount = 0;
}
}
}
last = now;
strcpy(buf, "");
for(i = 0; i < sizeof(m->backbuf); i++) {
int byte = m->backbuf[(m->backbuf_idx + i) % sizeof(m->backbuf)];
sprintf(&buf[i*3], " %02x", byte);
}
fifo_log(m, LOG_DEBUG, "%s on link '%s'. Last raw bits':%s\n", msg, m->name, buf);
mtp2_error_mon_count_frame(m);
mtp2_emon_count_error(m);
}
/* This MTP2 check bits calculation was nicked from zaptel.c, courtesy of
the GPL.
*/
#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
static unsigned short fcstab[256] =
{
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
/* Queue an MSU (in the retransmit buffer) for sending down the link. */
static void mtp2_queue_msu(mtp2_t *m, int sio, unsigned char *sif, int len) {
int i;
if(m->state != MTP2_INSERVICE) {
if(m->state != MTP2_READY) {
fifo_log(m, LOG_DEBUG, "Got MSU (sio=%d), but link not in service, discarding on link '%s'.\n", sio, m->name);
return;
}
}
if(len < 2) {
fifo_log(m, LOG_ERROR, "Got illegal MSU length %d < 2, dropping frame on link '%s'.\n", len, m->name);
return;
}
i = MTP_NEXT_SEQ(m->retrans_last_sent);
if(i == m->retrans_last_acked) {
fifo_log(m, LOG_WARNING, "MTP retransmit buffer full, MSU lost on link '%s'.\n", m->name);
return;
}
m->retrans_buf[i].buf[0] = 0; /* BSN Will be set correctly when transmitted */
m->retrans_buf[i].buf[1] = 0; /* FSN Will be set correctly when transmitted */
m->retrans_buf[i].buf[2] = (len >= 62 ? 63 : 1 + len);
m->retrans_buf[i].buf[3] = sio;
memcpy(&(m->retrans_buf[i].buf[4]), sif, len);
m->retrans_buf[i].len = len + 4;
m->retrans_last_sent = i;
/* Start transmitting the new SU, unless we were already (re-)transmitting. */
if(m->retrans_seq == -1) {
m->retrans_seq = i;
/* Start timer T7 "excessive delay of acknowledgement". */
mtp2_t7_start(m);
}
}
/* by lin.miao@openvox.cn */
void mtp3_put_label(int sls, ss7_variant variant, int opc, int dpc, unsigned char *buf) {
if(variant==ITU_SS7) {
buf[0] = dpc & 0xff;
buf[1] = ((dpc & 0x3f00) >> 8) | ((opc & 0x0003) << 6);
buf[2] = ((opc & 0x03fc) >> 2);
buf[3] = ((opc & 0x3c00) >> 10) | (sls << 4);
} else { /* CHINA SS7 */
buf[0] = dpc & 0xff;
buf[1] = (dpc & 0xff00) >> 8;
buf[2] = (dpc & 0xff0000) >> 16;
buf[3] = opc & 0xff;
buf[4] = (opc & 0xff00)>>8;
buf[5] = (opc & 0xff0000)>>16;
buf[6] = sls & 0x0f;
}
}
/* by lin.miao@openvox.cn */
static void mtp3_set_sls(ss7_variant variant, int sls, unsigned char *buf) {
if(variant==ITU_SS7)
buf[3] = (buf[3] & 0xff0f) | (sls << 4);
else /*China SS7 */
buf[6] = sls & 0x0f;
}
/* Handle Q.707 test-and-maintenance procedure.
Send a periodic SLTM message, listen for SLTA.
*/
static int mtp3_send_sltm(void *data); /* For mutual recursion */
static int timeout_sltm_t1(void *data) {
mtp2_t *m = data;
if(m->sltm_tries == 1) {
fifo_log(m, LOG_WARNING, "No SLTA received within Q.707 timer T1, trying again on link '%s'.\n", m->name);
mtp3_send_sltm(m);
m->sltm_tries = 2;
return 1; /* Ask to run again on next timer expire */
} else {
fifo_log(m, LOG_ERROR, "No SLTA received within Q.707 timer T1, faulting link on link '%s'.\n", m->name);
m->sltm_t1 = -1;
mtp3_link_fail(m, 0);
return 0; /* Do not re-schedule */
}
}
static unsigned char sltm_pattern[15] =
{ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
static int mtp3_send_sltm(void *data) {
unsigned char message_sltm[24]; /* increased to 24 bit to fit China variant by lin.miao@openvox.cn. */
mtp2_t *m = data;
int subservice = m->subservice;
if (subservice == -1)
subservice = 0x8;
fifo_log(m, LOG_EVENT, "Sending SLTM to peer on link '%s'....\n", m->name);
mtp3_put_label(m->sls, variant(m), this_host->opc, linkpeerpc(m), message_sltm);
if(variant(m)==ITU_SS7)
{
message_sltm[4] = 0x11; /* SLTM */
message_sltm[5] = 0xf0; /* Length: 15 */
memcpy(&(message_sltm[6]), sltm_pattern, sizeof(sltm_pattern));
mtp2_queue_msu(m, (subservice << 4) | 1, message_sltm, 6 + sizeof(sltm_pattern));
} else { /* CHINA SS7 */
message_sltm[7] = 0x11; /* SLTM */
message_sltm[8] = 0xf0; /* Length: 15 */
memcpy(&(message_sltm[9]), sltm_pattern, sizeof(sltm_pattern));
mtp2_queue_msu(m, (subservice << 4) | 1, message_sltm, 9 + sizeof(sltm_pattern));
}
/* Set up a timer to wait for SLTA. */
if(m->sltm_t1 == -1) { /* Only if it is not already running */
m->sltm_t1 = mtp_sched_add(mtp2_sched, 9000, timeout_sltm_t1, m);
m->sltm_tries = 1;
}
return 1; /* Ask to be run again on next timer expire */
}
/* Process a received link status signal unit. */
static void mtp2_process_lssu(mtp2_t *m, unsigned char *buf, int fsn, int fib) {
int typ;
typ = buf[3] & 0x07;
switch(typ) {
case 0: /* Status indication 'O' */
if(m->state == MTP2_NOT_ALIGNED) {
t2_stop(m);
t3_start(m);
m->state = MTP2_ALIGNED;
} else if(m->state == MTP2_PROVING) {
t4_stop(m);
m->state = MTP2_ALIGNED;
} else if(m->state == MTP2_READY) {
abort_initial_alignment(m);
} else if(m->state == MTP2_INSERVICE) {
fifo_log(m, LOG_NOTICE, "Got status indication 'O' while INSERVICE on link %s.\n", m->name);
mtp3_link_fail(m, 0);
}
break;
case 1: /* Status indication 'N' */
case 2: /* Status indication 'E' */
/* ToDo: This shouldn't really be here, I think. */
m->send_bsn = fsn;
m->send_bib = fib;
if(m->state == MTP2_NOT_ALIGNED) {
t2_stop(m);
t3_start(m);
m->state = MTP2_ALIGNED;
} else if(m->state == MTP2_ALIGNED) {
fifo_log(m, LOG_DEBUG, "Entering proving state for link '%s'.\n", m->name);
t3_stop(m);
t4_start(m);
m->state = MTP2_PROVING;
m->error_rate_mon = 0;
m->emon_ncount = 0;
} else if(m->state == MTP2_INSERVICE) {
fifo_log(m, LOG_NOTICE, "Got status indication 'N' or 'E' while INSERVICE on link '%s'.\n", m->name);
mtp3_link_fail(m, 0);
}
break;
case 3: /* Status indication 'OS' */
if(m->state == MTP2_ALIGNED || m->state == MTP2_PROVING) {
abort_initial_alignment(m);
} else if(m->state == MTP2_READY) {
fifo_log(m, LOG_NOTICE, "Got status indication 'OS' while READY on link '%s'.\n", m->name);
mtp3_link_fail(m, 1);
} else if(m->state == MTP2_INSERVICE) {
fifo_log(m, LOG_NOTICE, "Got status indication 'OS' while INSERVICE on link '%s'.\n", m->name);
mtp3_link_fail(m, 1);
}
break;
case 4: /* Status indication 'PO' */
/* ToDo: Not implemented. */
/* Don't do this, as the log would explode should this actually happen
fifo_log(LOG_NOTICE, "Status indication 'PO' not implemented.\n");
*/
break;
case 5: /* Status indication 'B' */
/* ToDo: Not implemented. */
fifo_log(m, LOG_NOTICE, "Status indication 'B' not implemented.\n");
break;
default: /* Illegal status indication. */
fifo_log(m, LOG_WARNING, "Got undefined LSSU status %d on link '%s'.\n", typ, m->name);
mtp3_link_fail(m, 0);
}
}
static void l4up(mtp2_t* m)
{
struct mtp_event link_up_event;
if (m->level4_up)
return;
m->level4_up = 1;
if (m->state == MTP2_INSERVICE) {
/* Tell user part about the successful link activation. */
link_up_event.typ = MTP_EVENT_STATUS;
link_up_event.status.link_state = MTP_EVENT_STATUS_LINK_UP;
link_up_event.status.link = m->link;
link_up_event.len = 0;
mtp_put(m, &link_up_event);
}
}
static void l4down(mtp2_t* m)
{
struct mtp_event link_down_event;
/* Notify user-parts. */
if (!m->level4_up)
return;
m->level4_up = 0;
link_down_event.typ = MTP_EVENT_STATUS;
link_down_event.status.link_state = MTP_EVENT_STATUS_LINK_DOWN;
link_down_event.status.link = m->link;
link_down_event.len = 0;
mtp_put(m, &link_down_event);
}
/* Process a received frame.
The frame has already been checked for correct crc and for being at least
5 bytes long.
*/
static void mtp2_good_frame(mtp2_t *m, unsigned char *buf, int len) {
int fsn, fib, bsn, bib;
int li;
/* Count this frame into the error rate monitor counters. */
mtp2_error_mon_count_frame(m);
#ifdef DROP_PACKETS_PCT
if(rand() <= DROP_PACKETS_PCT/100.0*RAND_MAX) {
return;
}
#endif
if(m->state == MTP2_DOWN) {
return;
}
log_frame(m, 0, buf, len);
bsn = buf[0] & 0x7f;
bib = buf[0] >> 7;
fsn = buf[1] & 0x7f;
fib = buf[1] >> 7;
li = buf[2] & 0x3f;
if(li + 3 > len) {
fifo_log(m, LOG_NOTICE, "Got unreasonable length indicator %d (len=%d) on link '%s'.\n",
li, len, m->name);
return;
}
if(li == 1 || li == 2) {
/* Link status signal unit. */
mtp2_process_lssu(m, buf, fsn, fib);
return;
}
/* Process the BSN of the signal unit.
According to Q.703 (5), only FISU and MSU should have FSN and BSN
processing done. */
if(m->state != MTP2_INSERVICE) {
if(m->state == MTP2_READY) {
t1_stop(m);
t7_stop(m);
m->send_fib = bib;
m->send_bsn = fsn;
m->send_bib = fib;
// m->retrans_last_acked = fsn;xxx
// m->retrans_last_sent = fsn;xxx
m->retrans_last_acked = bsn;//xxx
m->error_rate_mon = 0;
m->emon_dcount = 0;
m->emon_ncount = 0;
m->level4_up = 0;
/* Send TRA (traffic restart allowed) immediately, since we have no
routing capabilities that could be prohibited/restricted. */
m->state = MTP2_INSERVICE;
unsigned char message_tra[8]; /* by lin.miao@openvox.cn */
int subservice = m->subservice;
if (subservice == -1)
subservice = 0x8;
fifo_log(m, LOG_NOTICE, "Sending TRA to peer on link '%s'....\n", m->name);
mtp3_put_label(m->sls, variant(m), this_host->opc, linkpeerpc(m), message_tra);
if(variant(m)==ITU_SS7) {
message_tra[4] = 0x17; /* TRA */
mtp2_queue_msu(m, (subservice << 4) | 0, message_tra, 5);
} else { /* China SS7 */
message_tra[7] = 0x17; /* TRA */
mtp2_queue_msu(m, (subservice << 4) | 0, message_tra, 8);
}
/* Send an initial SLTM message, and send it periodic afterwards. */
if (m->send_sltm) {
mtp3_send_sltm(m);
if(m->sltm_t2 != -1) {
fifo_log(m, LOG_DEBUG, "SLTM timer T2 not cleared, restarted (%d)\n", m->sltm_t2);
mtp_sched_del(mtp2_sched, m->sltm_t2);
}
m->sltm_t2 = mtp_sched_add(mtp2_sched, 61000, mtp3_send_sltm, m);
}
else {
l4up(m);
}
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -