📄 x100p-ss7.c
字号:
sl_rc_stop(q, xp); ctrace(sl_txc_send_sios(q, xp)); sl_poc_stop(q, xp); /* ok if not ITUT */ xp->sl.statem.emergency = 0; xp->sl.statem.local_processor_outage = 0; xp->sl.statem.remote_processor_outage = 0; /* ok if not ANSI */ xp->sl.statem.lsc_state = SL_STATE_OUT_OF_SERVICE; } return (QR_DONE);}STATIC INLINE voidsl_txc_send_sib(queue_t *q, struct xp *xp){ xp->sl.statem.tx.sio = LSSU_SIB; xp->sl.statem.lssu_available = 1;}STATIC INLINE voidsl_txc_send_sipo(queue_t *q, struct xp *xp){ xp_timer_stop(xp, t7); if (xp->option.pvar == SS7_PVAR_ANSI_92) xp_timer_stop(xp, t6); xp->sl.statem.tx.sio = LSSU_SIPO; xp->sl.statem.lssu_available = 1;}STATIC INLINE voidsl_txc_send_sio(queue_t *q, struct xp *xp){ xp->sl.statem.tx.sio = LSSU_SIO; xp->sl.statem.lssu_available = 1;}STATIC INLINE voidsl_txc_send_sin(queue_t *q, struct xp *xp){ xp->sl.statem.tx.sio = LSSU_SIN; xp->sl.statem.lssu_available = 1;}STATIC INLINE voidsl_txc_send_sie(queue_t *q, struct xp *xp){ xp->sl.statem.tx.sio = LSSU_SIE; xp->sl.statem.lssu_available = 1;}STATIC INLINE voidsl_txc_send_msu(queue_t *q, struct xp *xp){ if (xp->sl.rtb.q_count) xp_timer_start(xp, t7); xp->sl.statem.msu_inhibited = 0; xp->sl.statem.lssu_available = 0;}STATIC INLINE voidsl_txc_send_fisu(queue_t *q, struct xp *xp){ xp_timer_stop(xp, t7); if (xp->option.pvar == SS7_PVAR_ANSI_92 && !(xp->option.popt & SS7_POPT_PCR)) xp_timer_stop(xp, t6); xp->sl.statem.msu_inhibited = 1; xp->sl.statem.lssu_available = 0;}STATIC INLINE voidsl_txc_fsnx_value(queue_t *q, struct xp *xp){ if (xp->sl.statem.tx.X.fsn != xp->sl.statem.rx.X.fsn) xp->sl.statem.tx.X.fsn = xp->sl.statem.rx.X.fsn;}STATIC INLINE voidsl_txc_nack_to_be_sent(queue_t *q, struct xp *xp){ xp->sl.statem.tx.N.bib = xp->sl.statem.tx.N.bib ? 0 : xp->sl.statem.ib_mask;}STATIC INLINE intsl_lsc_rtb_cleared(queue_t *q, struct xp *xp){ int err; if (xp->sl.statem.lsc_state == SL_STATE_PROCESSOR_OUTAGE) { xp->sl.statem.remote_processor_outage = 0; if (xp->sl.statem.local_processor_outage) return (QR_DONE); if ((err = sl_remote_processor_recovered_ind(q, xp))) return (err); if ((err = sl_rtb_cleared_ind(q, xp))) return (err); sl_txc_send_msu(q, xp); xp->sl.statem.lsc_state = SL_STATE_IN_SERVICE; } return (QR_DONE);}STATIC void sl_check_congestion(queue_t *q, struct xp *xp);STATIC INLINE voidsl_txc_bsnr_and_bibr(queue_t *q, struct xp *xp){ int pcr = xp->option.popt & SS7_POPT_PCR; xp->sl.statem.tx.R.bsn = xp->sl.statem.rx.R.bsn; xp->sl.statem.tx.R.bib = xp->sl.statem.rx.R.bib; if (xp->sl.statem.clear_rtb) { bufq_purge(&xp->sl.rtb); xp->sl.statem.Ct = 0; sl_check_congestion(q, xp); xp->sl.statem.tx.F.fsn = (xp->sl.statem.tx.R.bsn + 1) & xp->sl.statem.sn_mask; xp->sl.statem.tx.L.fsn = xp->sl.statem.tx.R.bsn; xp->sl.statem.tx.N.fsn = xp->sl.statem.tx.R.bsn; xp->sl.statem.tx.N.fib = xp->sl.statem.tx.R.bib; xp->sl.statem.Z = (xp->sl.statem.tx.R.bsn + 1) & xp->sl.statem.sn_mask; xp->sl.statem.z_ptr = NULL; /* FIXME: handle error return */ sl_lsc_rtb_cleared(q, xp); xp->sl.statem.clear_rtb = 0; xp->sl.statem.rtb_full = 0; return; } if (xp->sl.statem.tx.F.fsn != ((xp->sl.statem.tx.R.bsn + 1) & xp->sl.statem.sn_mask)) { if (xp->sl.statem.sib_received) { xp->sl.statem.sib_received = 0; xp_timer_stop(xp, t6); } do { freemsg(bufq_dequeue(&xp->sl.rtb)); xp->sl.statem.Ct--; xp->sl.statem.tx.F.fsn = (xp->sl.statem.tx.F.fsn + 1) & xp->sl.statem.sn_mask; } while (xp->sl.statem.tx.F.fsn != ((xp->sl.statem.tx.R.bsn + 1) & xp->sl.statem.sn_mask)); sl_check_congestion(q, xp); if (xp->sl.rtb.q_count == 0) { xp_timer_stop(xp, t7); } else { xp_timer_start(xp, t7); } if (!pcr || (xp->sl.rtb.q_msgs < xp->sl.config.N1 && xp->sl.rtb.q_count < xp->sl.config.N2)) xp->sl.statem.rtb_full = 0; if (SN_OUTSIDE(xp->sl.statem.tx.F.fsn, xp->sl.statem.Z, xp->sl.statem.tx.L.fsn) || !xp->sl.rtb.q_count) { xp->sl.statem.Z = xp->sl.statem.tx.F.fsn; xp->sl.statem.z_ptr = xp->sl.rtb.q_head; } } if (pcr) return; if (xp->sl.statem.tx.N.fib != xp->sl.statem.tx.R.bib) { if (xp->sl.statem.sib_received) { xp->sl.statem.sib_received = 0; xp_timer_stop(xp, t6); } xp->sl.statem.tx.N.fib = xp->sl.statem.tx.R.bib; xp->sl.statem.tx.N.fsn = (xp->sl.statem.tx.F.fsn - 1) & xp->sl.statem.sn_mask; if ((xp->sl.statem.z_ptr = xp->sl.rtb.q_head) != NULL) xp->sl.statem.retrans_cycle = 1; return; }}STATIC INLINE voidsl_txc_sib_received(queue_t *q, struct xp *xp){ /* FIXME: consider these variations for all */ if (xp->option.pvar == SS7_PVAR_ANSI_92 && xp->sl.statem.lssu_available) if (xp->sl.statem.tx.sio != LSSU_SIB) return; if (xp->option.pvar != SS7_PVAR_ITUT_93 && !xp->sl.rtb.q_count) return; if (!xp->sl.statem.sib_received) { xp_timer_start(xp, t6); xp->sl.statem.sib_received = 1; } xp_timer_start(xp, t7);}STATIC INLINE voidsl_txc_clear_rtb(queue_t *q, struct xp *xp){ bufq_purge(&xp->sl.rtb); xp->sl.statem.Ct = 0; xp->sl.statem.clear_rtb = 1; xp->sl.statem.rtb_full = 0; /* added */ /* FIXME: should probably follow more of the ITUT flush_buffers stuff like reseting Z and FSNF, FSNL, FSNT. */ sl_check_congestion(q, xp);}STATIC INLINE voidsl_txc_clear_tb(queue_t *q, struct xp *xp){ bufq_purge(&xp->sl.tb); flushq(xp->iq, FLUSHDATA); xp->sl.statem.Cm = 0; sl_check_congestion(q, xp);}STATIC INLINE voidsl_txc_flush_buffers(queue_t *q, struct xp *xp){ bufq_purge(&xp->sl.rtb); xp->sl.statem.rtb_full = 0; xp->sl.statem.Ct = 0; bufq_purge(&xp->sl.tb); flushq(xp->iq, FLUSHDATA); xp->sl.statem.Cm = 0; xp->sl.statem.Z = 0; xp->sl.statem.z_ptr = NULL; /* Z =0 error in ITUT 93 and ANSI */ xp->sl.statem.Z = xp->sl.statem.tx.F.fsn = (xp->sl.statem.tx.R.bsn + 1) & xp->sl.statem.sn_mask; xp->sl.statem.tx.L.fsn = xp->sl.statem.rx.R.bsn; xp->sl.statem.rx.T.fsn = xp->sl.statem.rx.R.bsn; xp_timer_stop(xp, t7); return;}STATIC INLINE voidsl_rc_fsnt_value(queue_t *q, struct xp *xp){ xp->sl.statem.rx.T.fsn = xp->sl.statem.tx.N.fsn;}STATIC INLINE intsl_txc_retrieval_request_and_fsnc(queue_t *q, struct xp *xp, sl_ulong fsnc){ mblk_t *mp; int err; xp->sl.statem.tx.C.fsn = fsnc & (xp->sl.statem.sn_mask); /* * FIXME: Q.704/5.7.2 states: * * 5.7.2 If a changeover order or acknowledgement containing an unreasonable value of the forward * sequence number is received, no buffer updating or retrieval is performed, and new traffic is started * on the alternative signalling link(s). * * It will be necessary to check FSNC for "reasonableness" here and flush RTB and TB and return * retrieval-complete indication with a return code of "unreasonable FSNC". * * (Tell the SIGTRAN working group and M2UA guys about this!) */ while (xp->sl.rtb.q_count && xp->sl.statem.tx.F.fsn != ((fsnc + 1) & xp->sl.statem.sn_mask)) { freemsg(bufq_dequeue(&xp->sl.rtb)); xp->sl.statem.Ct--; xp->sl.statem.tx.F.fsn = (xp->sl.statem.tx.F.fsn + 1) & xp->sl.statem.sn_mask; } while ((mp = bufq_dequeue(&xp->sl.tb))) { xp->sl.statem.Cm--; bufq_queue(&xp->sl.rtb, mp); xp->sl.statem.Ct++; if (!xp->sl.statem.Cm) qenable(xp->iq); } xp->sl.statem.Z = xp->sl.statem.tx.F.fsn = (xp->sl.statem.tx.C.fsn + 1) & xp->sl.statem.sn_mask; while ((mp = bufq_dequeue(&xp->sl.rtb))) { xp->sl.statem.Ct--; if ((err = sl_retrieved_message_ind(q, xp, mp))) return (err); } xp->sl.statem.rtb_full = 0; if ((err = sl_retrieval_complete_ind(q, xp))) return (err); xp->sl.statem.Cm = 0; xp->sl.statem.Ct = 0; xp->sl.statem.tx.N.fsn = xp->sl.statem.tx.L.fsn = xp->sl.statem.tx.C.fsn; return (QR_DONE);}STATIC INLINE voidsl_daedt_fisu(queue_t *q, struct xp *xp, mblk_t *mp){ if (xp->option.popt & SS7_POPT_XSN) { *(sl_ushort *) mp->b_wptr = htons(xp->sl.statem.tx.N.bsn | xp->sl.statem.tx.N.bib); mp->b_wptr += sizeof(sl_ushort); *(sl_ushort *) mp->b_wptr = htons(xp->sl.statem.tx.N.fsn | xp->sl.statem.tx.N.fib); mp->b_wptr += sizeof(sl_ushort); *(sl_ushort *) mp->b_wptr = 0; mp->b_wptr += sizeof(sl_ushort); } else { *(sl_uchar *) mp->b_wptr = (xp->sl.statem.tx.N.bsn | xp->sl.statem.tx.N.bib); mp->b_wptr += sizeof(sl_uchar); *(sl_uchar *) mp->b_wptr = (xp->sl.statem.tx.N.fsn | xp->sl.statem.tx.N.fib); mp->b_wptr += sizeof(sl_uchar); *(sl_uchar *) mp->b_wptr = 0; mp->b_wptr += sizeof(sl_uchar); }}STATIC INLINE voidsl_daedt_lssu(queue_t *q, struct xp *xp, mblk_t *mp){ if (xp->option.popt & SS7_POPT_XSN) { *(sl_ushort *) mp->b_wptr = htons(xp->sl.statem.tx.N.bsn | xp->sl.statem.tx.N.bib); mp->b_wptr += sizeof(sl_ushort); *(sl_ushort *) mp->b_wptr = htons(xp->sl.statem.tx.N.fsn | xp->sl.statem.tx.N.fib); mp->b_wptr += sizeof(sl_ushort); *(sl_ushort *) mp->b_wptr = htons(1); mp->b_wptr += sizeof(sl_ushort); } else { *(sl_uchar *) mp->b_wptr = (xp->sl.statem.tx.N.bsn | xp->sl.statem.tx.N.bib); mp->b_wptr += sizeof(sl_uchar); *(sl_uchar *) mp->b_wptr = (xp->sl.statem.tx.N.fsn | xp->sl.statem.tx.N.fib); mp->b_wptr += sizeof(sl_uchar); *(sl_uchar *) mp->b_wptr = 1; mp->b_wptr += sizeof(sl_uchar); } *(sl_uchar *) mp->b_wptr = (xp->sl.statem.tx.sio); mp->b_wptr += sizeof(sl_uchar);}STATIC INLINE voidsl_daedt_msu(queue_t *q, struct xp *xp, mblk_t *mp){ int len = msgdsize(mp); if (xp->option.popt & SS7_POPT_XSN) { ((sl_ushort *) mp->b_rptr)[0] = htons(xp->sl.statem.tx.N.bsn | xp->sl.statem.tx.N.bib); ((sl_ushort *) mp->b_rptr)[1] = htons(xp->sl.statem.tx.N.fsn | xp->sl.statem.tx.N.fib); ((sl_ushort *) mp->b_rptr)[2] = htons(len - 6 < 512 ? len - 6 : 511); } else { ((sl_uchar *) mp->b_rptr)[0] = (xp->sl.statem.tx.N.bsn | xp->sl.statem.tx.N.bib); ((sl_uchar *) mp->b_rptr)[1] = (xp->sl.statem.tx.N.fsn | xp->sl.statem.tx.N.fib); ((sl_uchar *) mp->b_rptr)[2] = (len - 3 < 64 ? len - 3 : 63); }}STATIC INLINE mblk_t *sl_txc_transmission_request(queue_t *q, struct xp *xp){ mblk_t *mp = NULL; int pcr; if (xp->sl.statem.txc_state != SL_STATE_IN_SERVICE) return (mp); pcr = xp->option.popt & SS7_POPT_PCR; if (xp->sl.statem.lssu_available) { if ((mp = ss7_fast_allocb(&xp_bufpool, 7, BPRI_HI))) { if (xp->sl.statem.tx.sio == LSSU_SIB) xp->sl.statem.lssu_available = 0; xp->sl.statem.tx.N.fsn = xp->sl.statem.tx.L.fsn; xp->sl.statem.tx.N.bib = xp->sl.statem.tx.N.bib; xp->sl.statem.tx.N.bsn = (xp->sl.statem.tx.X.fsn - 1) & xp->sl.statem.sn_mask; xp->sl.statem.tx.N.fib = xp->sl.statem.tx.N.fib; sl_daedt_lssu(q, xp, mp); } return (mp); } if (xp->sl.statem.msu_inhibited) { if ((mp = ss7_fast_allocb(&xp_bufpool, 6, BPRI_HI))) { xp->sl.statem.tx.N.fsn = xp->sl.statem.tx.L.fsn; xp->sl.statem.tx.N.bib = xp->sl.statem.tx.N.bib; xp->sl.statem.tx.N.bsn = (xp->sl.statem.tx.X.fsn - 1) & xp->sl.statem.sn_mask; xp->sl.statem.tx.N.fib = xp->sl.statem.tx.N.fib; sl_daedt_fisu(q, xp, mp); } return (mp); } if (pcr) { if ((xp->sl.rtb.q_msgs < xp->sl.config.N1) && (xp->sl.rtb.q_count < xp->sl.config.N2)) { xp->sl.statem.forced_retransmission = 0; xp->sl.statem.rtb_full = 0; } if (xp->sl.tb.q_count && xp->sl.statem.rtb_full) { xp->sl.statem.forced_retransmission = 1; } } if ((!pcr && xp->sl.statem.retrans_cycle) || (pcr && (xp->sl.statem.forced_retransmission || (!xp->sl.tb.q_count && xp->sl.rtb.q_count)))) { mblk_t *bp; if ((bp = xp->sl.statem.z_ptr) && !(mp = dupmsg(bp))) return (mp); if (!bp && pcr) { if ((bp = xp->sl.statem.z_ptr = xp->sl.rtb.q_head) && !(mp = dupmsg(bp))) return (mp); xp->sl.statem.Z = xp->sl.statem.tx.F.fsn; } if (mp) { xp->sl.statem.z_ptr = bp->b_next; if (pcr) { xp->sl.statem.tx.N.fsn = xp->sl.statem.Z; xp->sl.statem.tx.N.fib = xp->sl.statem.tx.N.fib; xp->sl.statem.tx.N.bsn = (xp->sl.statem.tx.X.fsn - 1) & xp->sl.statem.sn_mask; xp->sl.statem.tx.N.bib = xp->sl.statem.tx.N.bib; xp->sl.statem.Z = (xp->sl.statem.Z + 1) & xp->sl.statem.sn_mask; } else { xp->sl.statem.tx.N.fsn = (xp->sl.statem.tx.N.fsn + 1) & xp->sl.statem.sn_mask; xp->sl.statem.tx.N.fib = xp->sl.statem.tx.N.fib; xp->sl.statem.tx.N.bsn = (xp->sl.statem.tx.X.fsn - 1) & xp->sl.statem.sn_mask; xp->sl.statem.tx.N.bib = xp->sl.statem.tx.N.bib; } sl_daedt_msu(q, xp, mp); if (xp->sl.statem.tx.N.fsn == xp->sl.statem.tx.L.fsn || xp->sl.statem.z_ptr == NULL) xp->sl.statem.retrans_cycle = 0; } return (mp); } if ((!pcr && (!xp->sl.tb.q_count || xp->sl.statem.rtb_full)) || (pcr && (!xp->sl.tb.q_count && !xp->sl.rtb.q_count))) { if ((mp = ss7_fast_allocb(&xp_bufpool, 6, BPRI_HI))) { xp->sl.statem.tx.N.fsn = xp->sl.statem.tx.L.fsn; xp->sl.statem.tx.N.bib = xp->sl.statem.tx.N.bib; xp->sl.statem.tx.N.bsn = (xp->sl.statem.tx.X.fsn - 1) & xp->sl.statem.sn_mask; xp->sl.statem.tx.N.fib = xp->sl.statem.tx.N.fib; sl_daedt_fisu(q, xp, mp); } return (mp); } else { spin_lock(&xp->sl.tb.q_lock); if ((mp = bufq_head(&xp->sl.tb)) && (mp = dupmsg(mp))) { mblk_t *bp = bufq_dequeue(&xp->sl.tb); xp->sl.statem.Cm--; if (!xp->sl.statem.Cm) qenable(xp->iq); xp->sl.statem.tx.L.fsn = (xp->sl.statem.tx.L.fsn + 1) & xp->sl.statem.sn_mask; xp->sl.statem.tx.N.fsn = xp->sl.statem.tx.L.fsn; if (!xp->sl.rtb.q_count) xp_timer_start(xp, t7); bufq_queue(&xp->sl.rtb, bp); xp->sl.statem.Ct++; sl_rc_fsnt_value(q, xp); if (pcr) { if ((xp->sl.rtb.q_msgs >= xp->sl.config.N1) || (xp->sl.rtb.q_count >= xp->sl.config.N2)) { xp->sl.statem.rtb_full = 1; xp->sl.statem.forced_retransmission = 1; } } else { if ((xp->sl.rtb.q_msgs >= xp->sl.config.N1) || (xp->sl.rtb.q_count >= xp->sl.config.N2) || (xp->sl.statem.tx.L.fsn == ((xp->sl.statem.tx.F.fsn - 2) & xp->sl.statem.sn_mask))) xp->sl.statem.rtb_full = 1; } xp->sl.statem.tx.N.bib = xp->sl.statem.tx.N.bib; xp->sl.statem.tx.N.bsn = (xp->sl.statem.tx.X.fsn - 1) & xp->sl.statem.sn_mask; xp->sl.statem.tx.N.fib = xp->sl.statem.tx.N.fib; sl_daedt_msu(q, xp, mp); } spin_unlock(&xp->sl.tb.q_lock); return (mp); }}STATIC INLINE voidsl_daedr_start(queue_t *q, struct xp *xp){ xp->sdt.statem.daedr_state = SDT_STATE_IN_SERVICE; xp->sdl.statem.rx_state = SDL_STATE_IN_SERVICE; xp->sdl.config.ifflags |= (SDL_IF_UP | SDL_IF_RX_RUNNING);}STATIC INLINE voidsl_rc_start(queue_t *q, struct xp *xp){ if (xp->sl.statem.rc_state == SL_STATE_IDLE) { xp->sl.statem.rx.X.fsn = 0; xp->sl.statem.rx.X.fib = xp->sl.statem.ib_mask; xp->sl.statem.rx.F.fsn = 0; xp->sl.statem.rx.T.fsn = xp->sl.statem.sn_mask; xp->sl.statem.rtr = 0; /* Basic only (note 1). */ if (xp->option.pvar == SS7_PVAR_ANSI_92) xp->sl.statem.msu_fisu_accepted = 1; else xp->sl.statem.msu_fisu_accepted = 0; xp->sl.statem.abnormal_bsnr = 0; xp->sl.statem.abnormal_fibr = 0; /* Basic only (note 1). */ xp->sl.statem.congestion_discard = 0; xp->sl.statem.congestion_accept = 0; sl_daedr_start(q, xp); xp->sl.statem.rc_state = SL_STATE_IN_SERVICE; return; /* * Note 1 - Although rtr and abnormal_fibr are only applicable to the Basic procedure (and * not PCR), these state machine variables are never examined by PCR routines, so PCR and * basic can share the same start procedures. */ }}STATIC INLINE voidsl_rc_reject_msu_fisu(queue_t *q, struct xp *xp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -