📄 mtp.c
字号:
static void t17_stop(mtp2_t *m) { if(m->mtp3_t17 != -1) { mtp_sched_del(mtp2_sched, m->mtp3_t17); m->mtp3_t17 = -1; }}static void t17_start(mtp2_t *m) { t17_stop(m); m->mtp3_t17 = mtp_sched_add(mtp2_sched, 1200, t17_timeout, m);}static int t1_timeout(void *data) { mtp2_t *m = data; fifo_log(m, LOG_WARNING, "MTP2 timer T1 timeout (peer failed to complete " "initial alignment), initial alignment failed on link '%s'.\n", m->name); m->mtp2_t1 = -1; abort_initial_alignment(m); return 0; /* Do not re-schedule */}static void t1_stop(mtp2_t *m) { if(m->mtp2_t1 != -1) { mtp_sched_del(mtp2_sched, m->mtp2_t1); m->mtp2_t1 = -1; }}static void t1_start(mtp2_t *m) { t1_stop(m); m->mtp2_t1 = mtp_sched_add(mtp2_sched, 45000, t1_timeout, m);}static int t2_timeout(void *data) { mtp2_t *m = data; fifo_log(m, LOG_WARNING, "MTP2 timer T2 timeout (failed to receive 'O', 'N', " "or 'E' after sending 'O'), initial alignment failed on link '%s'.\n", m->name); m->mtp2_t2 = -1; abort_initial_alignment(m); return 0; /* Do not re-schedule */}static void t2_stop(mtp2_t *m) { if(m->mtp2_t2 != -1) { mtp_sched_del(mtp2_sched, m->mtp2_t2); m->mtp2_t2 = -1; }}static void t2_start(mtp2_t *m) { t2_stop(m); m->mtp2_t2 = mtp_sched_add(mtp2_sched, 75000, t2_timeout, m);}static int t3_timeout(void *data) { mtp2_t *m = data; fifo_log(m, LOG_WARNING, "MTP2 timer T3 timeout (failed to receive 'N', " "or 'E' after sending 'O'), initial alignment failed on link '%s'.\n", m->name); m->mtp2_t3 = -1; abort_initial_alignment(m); return 0; /* Do not re-schedule */}static void t3_stop(mtp2_t *m) { if(m->mtp2_t3 != -1) { mtp_sched_del(mtp2_sched, m->mtp2_t3); m->mtp2_t3 = -1; }}static void t3_start(mtp2_t *m) { t3_stop(m); m->mtp2_t3 = mtp_sched_add(mtp2_sched, 1500, t3_timeout, m);}static int t4_timeout(void *data) { mtp2_t *m = data; fifo_log(m, LOG_DEBUG, "Proving successful on link '%s'.\n", m->name); m->state = MTP2_READY; m->mtp2_t4 = -1; t1_start(m); return 0; /* Do not re-schedule */}static void t4_stop(mtp2_t *m) { if(m->mtp2_t4 != -1) { mtp_sched_del(mtp2_sched, m->mtp2_t4); m->mtp2_t4 = -1; }}static void t4_start(mtp2_t *m) { t4_stop(m); m->mtp2_t4 = mtp_sched_add(mtp2_sched, 500, t4_timeout, m);}static struct mtp2_state* get_inservice_schannel(struct link* link){ int i; for (i = 0; i < this_host->n_schannels; i++) { struct mtp2_state* m = &mtp2_state[i]; if (m->state == MTP2_INSERVICE) { struct link* slink = m->link; if (link->linkset == slink->linkset || is_combined_linkset(link->linkset, slink->linkset)) return m; } } return NULL;}int mtp_has_inservice_schannels(struct link* link){ return (get_inservice_schannel(link) != NULL);}static mtp2_t* find_alternative_slink(mtp2_t* m){ struct mtp2_state* newm = NULL; struct mtp2_state* alt_newm = NULL; int i; for (i = 0; i < this_host->n_schannels; i++) { if (&mtp2_state[i] == m) continue; if (mtp2_state[i].state != MTP2_INSERVICE) continue; if (m->link->linkset == mtp2_state[i].link->linkset) { newm = &mtp2_state[i]; break; } if (is_combined_linkset(m->link->linkset, mtp2_state[i].link->linkset)) alt_newm = &mtp2_state[i]; } if (!newm) newm = alt_newm; return newm;}/* Flush MTP transmit buffer to other link or host */static void mtp_changeover(mtp2_t *m) { struct mtp2_state* newm = NULL; int i; int do_forward = 1; for (i = 0; i < this_host->n_schannels; i++) { struct mtp2_state* newm = &mtp2_state[i]; if (&mtp2_state[i] == m) continue; if (m->link->linkset != newm->link->linkset) continue; if (mtp2_state[i].state == MTP2_INSERVICE) { newm = &mtp2_state[i]; break; } } if (!newm) { fifo_log(m, LOG_NOTICE, "MTP changeover last_ack=%d, last_sent=%d, from schannel %d, no INSERVICE schannel found\n", m->retrans_last_acked, m->retrans_last_sent, m->schannel); if (this_host->has_signalling_receivers) fifo_log(m, LOG_NOTICE, "Failover, using another host for signalling.\n"); if (!cluster_receivers_alive(m->link->linkset)) { fifo_log(m, LOG_NOTICE, "Failover not possible, no other signalling link and no other host available.\n");#if 1 /* Remove all MSU's - the user parts must deal with lost PDU's */ m->retrans_last_acked = MTP_NEXT_SEQ(m->retrans_last_sent); m->retrans_seq = -1;#endif return; } } fifo_log(m, LOG_NOTICE, "MTP changeover last_ack=%d, last_sent=%d, from schannel %d, to schannel %d\n", m->retrans_last_acked, m->retrans_last_sent, m->schannel, newm ? newm->schannel : -1); i = MTP_NEXT_SEQ(m->retrans_last_acked); while (i != MTP_NEXT_SEQ(m->retrans_last_sent)) { int sio = m->retrans_buf[i].buf[3]; int len = m->retrans_buf[i].len-4; unsigned char* buf = &m->retrans_buf[i].buf[4]; fifo_log(m, LOG_DEBUG, "MTP changeover seqno=%d, sio=%d, len=%d, is_moved=%d\n", i, sio, len, (sio & 0xf) > 3); if (do_forward && ((sio & 0xf) >= 3)) { /* User and application parts */ if (newm) { mtp2_queue_msu(newm, sio, buf, len); } else { if ((sio & 0xf) == 0x5 /* ISUP */) { unsigned char reqbuf[MTP_REQ_MAX_SIZE]; struct mtp_req *req = (struct mtp_req*) &reqbuf; memcpy(req->buf, buf, len); req->len = len; req->typ = MTP_REQ_ISUP; cluster_mtp_forward(req); } } m->retrans_buf[i].buf[3] = 0; m->retrans_buf[i].len = 5; /* Is now a LSSU */ m->retrans_buf[i].buf[3] = 2; i = MTP_NEXT_SEQ(i); } }}/* Called on link errors that occur during initial alignment (before the link is in service), and which should cause initial alignment to be aborted. The initial alignment to be re-tried after a short delay (MTP3 T17). */static void abort_initial_alignment(mtp2_t *m){ mtp2_cleanup(m); m->state = MTP2_DOWN; /* Retry the initial alignment after a small delay. */ t17_start(m); fifo_log(m, LOG_DEBUG, "Aborted initial alignment on link '%s'.\n", m->name);}/* Called on link errors that occur after the link is brought into service and which must cause the link to be brought out of service. This entails notifying user-parts of the failure and initiating MTP3 link failover, when that is implemented. */static void mtp3_link_fail(mtp2_t *m, int down) { struct mtp_event link_up_event; int old_state = m->state; mtp2_cleanup(m); /* Notify user-parts. */ if(old_state == MTP2_INSERVICE) { link_up_event.typ = MTP_EVENT_STATUS; link_up_event.status.link_state = MTP_EVENT_STATUS_LINK_DOWN; link_up_event.status.link = m->link; link_up_event.len = 0; mtp_put(m, &link_up_event); mtp_changeover(m); } /* For now, restart initial alignment after a small delay. */ if (down) { m->state = MTP2_DOWN; t17_start(m); } else m->state = MTP2_NOT_ALIGNED; l4down(m); fifo_log(m, LOG_DEBUG, "Fail on link '%s'.\n", m->name);}static void start_initial_alignment(mtp2_t *m, char* reason) { m->state = MTP2_NOT_ALIGNED; m->send_fib = 1; m->send_bsn = 0x7f; m->send_bib = 1; m->tx_len = 0; m->tx_sofar = 0; m->retrans_seq = -1; m->retrans_last_acked = 0x7f; m->retrans_last_sent = 0x7f; m->error_rate_mon = 0; m->emon_dcount = 0; m->emon_ncount = 0; m->bsn_errors = 0; fifo_log(m, LOG_DEBUG, "Starting initial alignment on link '%s', reason: %s.\n", m->name, reason); t2_start(m);}static void t7_stop(mtp2_t *m) { if(m->mtp2_t7 != -1) { mtp_sched_del(mtp2_sched, m->mtp2_t7); m->mtp2_t7 = -1; }}static void mtp2_cleanup(mtp2_t *m) { /* Stop SLTA response timeout. */ if(m->sltm_t1 != -1) { mtp_sched_del(mtp2_sched, m->sltm_t1); m->sltm_t1 = -1; } /* Stop sending SLTM. */ if(m->sltm_t2 != -1) { mtp_sched_del(mtp2_sched, m->sltm_t2); m->sltm_t2 = -1; } t1_stop(m); t2_stop(m); t3_stop(m); t4_stop(m); t7_stop(m); t17_stop(m);}static void deliver_l4(mtp2_t *m, unsigned char *sif, int len, int sio) { unsigned char ebuf[MTP_EVENT_MAX_SIZE]; struct mtp_event *event = (struct mtp_event *)ebuf; if (sio == MTP_EVENT_ISUP) { event->isup.link = NULL; event->isup.slink = m->link; event->isup.slinkix = m->link->linkix; } else{ event->sccp.slink = m->link; event->sccp.slinkix = m->link->linkix; } event->typ = sio; event->len = len; memcpy(event->buf, sif, len); mtp_put(m, event);}static int timeout_t7(void *data) { mtp2_t *m = data; m->mtp2_t7 = -1; fifo_log(m, LOG_WARNING, "T7 timeout (excessive delay of acknowledgement) on link '%s', state=%d.\n", m->name, m->state); mtp3_link_fail(m, 1); return 0; /* Do not schedule us again. */}static void mtp2_t7_start(mtp2_t *m) { t7_stop(m); m->mtp2_t7 = mtp_sched_add(mtp2_sched, 1500, timeout_t7, m);}/* Signal unit error rate monitor (Q.703 (10.2)) */static void mtp2_error_mon_count_frame(mtp2_t *m) { if(m->state == MTP2_READY || m->state == MTP2_INSERVICE) { m->emon_dcount = (m->emon_dcount + 1) % 256; if(m->emon_dcount == 0 && m->error_rate_mon > 0) { (m->error_rate_mon)--; } }}static void mtp2_octet_counting(mtp2_t *m) { m->emon_ncount = 0;}static void mtp2_emon_count_error(mtp2_t *m) { if(m->state == MTP2_READY || m->state == MTP2_INSERVICE) { if(m->error_rate_mon < 64) { (m->error_rate_mon)++; if(m->error_rate_mon == 64) { fifo_log(m, LOG_WARNING, "Excessive errors detected in signalling unit " "error rate monitor, link failed on link '%s'.\n", m->name); mtp3_link_fail(m, 0); } } } else if(m->state == MTP2_PROVING) { (m->error_rate_mon)++; /* ToDo: For now we are always in emergency, but for non emergency, proving is not aborted until error_rate_mon reaches the value of 4 (Q.703 (10.3.4)). */ if(m->error_rate_mon >= 1) { fifo_log(m, LOG_WARNING, "Excessive errors detected in alignment " "error rate monitor, link failed on link '%s'.\n", m->name); 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -