📄 sl_sm.h
字号:
/***************************************************************************** @(#) sl_sm.h,v 0.7.8.1 2001/12/11 13:15:40 brian Exp ----------------------------------------------------------------------------- Copyright (C) 1997-2001 Brian Bidulock <bidulock@dallas.net> All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ----------------------------------------------------------------------------- Last Modified 2001/12/11 13:15:40 by brian *****************************************************************************/#ifndef __SL_SM_H__#define __SL_SM_H__/* * ======================================================================= * * PROTOCOL STATE MACHINE FUNCTIONS * * ======================================================================= */#define SN_OUTSIDE(lower,middle,upper) \ ( ( (lower) <= (upper) ) \ ? ( ( (middle) < (lower) ) || ( (middle) > (upper) ) ) \ : ( ( (middle) < (lower) ) && ( (middle) > (upper) ) ) \ )#define sl_timer_stop(tim) \{ \ if (sl->timers.tim) \ untimeout(sl->timers.tim); \}#define sl_timer_start(tim) \{ \ sl_timer_stop(tim); \ sl->timers.tim= \ timeout((timo_fcn_t *)sl_ ## tim ## _timeout,(caddr_t)sl,sl->config.tim); \}#define sl_timer_start_t4(val) \{ \ sl_timer_stop(t4); \ sl->timers.t4 = \ timeout((timo_fcn_t *)sl_t4_timeout,(caddr_t)sl,sl->statem.val); \}static inline void sl_daedt_fisu(sl_t *sl){ mblk_t *mp; if ( (mp = allocb(6, BPRI_HI)) ) { if ( sl->option.popt & SS7_POPT_XSN ) { *((sl_ushort *)mp->b_wptr)++ = htons(sl->statem.tx.N.bsn|sl->statem.tx.N.bib); *((sl_ushort *)mp->b_wptr)++ = htons(sl->statem.tx.N.fsn|sl->statem.tx.N.fib); *((sl_ushort *)mp->b_wptr)++ = 0; } else { *((sl_uchar *)mp->b_wptr)++ = (sl->statem.tx.N.bsn|sl->statem.tx.N.bib); *((sl_uchar *)mp->b_wptr)++ = (sl->statem.tx.N.fsn|sl->statem.tx.N.fib); *((sl_uchar *)mp->b_wptr)++ = 0; }#if 0 ptrace(("tx: bsn=%x, bib=%x, fsn=%x, fib=%x, len=%d, sio=%d\n", sl->statem.tx.N.bsn, sl->statem.tx.N.bib, sl->statem.tx.N.fsn, sl->statem.tx.N.fib, 0, 0 ));#endif sl->dcalls->daedt_xmit(sl, mp); } sl->statem.txc_state = SL_STATE_SLEEPING;}static inline void sl_daedt_lssu(sl_t *sl){ mblk_t *mp = allocb(7, BPRI_HI); if ( mp ) { if ( sl->option.popt & SS7_POPT_XSN ) { *((sl_ushort *)mp->b_wptr)++ = htons(sl->statem.tx.N.bsn|sl->statem.tx.N.bib); *((sl_ushort *)mp->b_wptr)++ = htons(sl->statem.tx.N.fsn|sl->statem.tx.N.fib); *((sl_ushort *)mp->b_wptr)++ = htons(1); } else { *((sl_uchar *)mp->b_wptr)++ = (sl->statem.tx.N.bsn|sl->statem.tx.N.bib); *((sl_uchar *)mp->b_wptr)++ = (sl->statem.tx.N.fsn|sl->statem.tx.N.fib); *((sl_uchar *)mp->b_wptr)++ = 1; } *((sl_uchar *)mp->b_wptr)++ = (sl->statem.tx.sio);#if 0 ptrace(("tx: bsn=%x, bib=%x, fsn=%x, fib=%x, len=%d, sio=%d\n", sl->statem.tx.N.bsn, sl->statem.tx.N.bib, sl->statem.tx.N.fsn, sl->statem.tx.N.fib, 1, sl->statem.tx.sio ));#endif sl->dcalls->daedt_xmit(sl, mp); } if ( sl->statem.lssu_available ) sl->statem.txc_state = SL_STATE_SLEEPING;}static inline void sl_daedt_msu(sl_t *sl, mblk_t *md){ mblk_t *mp = dupb(md); if ( mp ) { int len = msgdsize(mp); if ( sl->option.popt & SS7_POPT_XSN ) { ((sl_ushort *)mp->b_rptr)[0] = htons(sl->statem.tx.N.bsn|sl->statem.tx.N.bib); ((sl_ushort *)mp->b_rptr)[1] = htons(sl->statem.tx.N.fsn|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] = (sl->statem.tx.N.bsn|sl->statem.tx.N.bib); ((sl_uchar *)mp->b_rptr)[1] = (sl->statem.tx.N.fsn|sl->statem.tx.N.fib); ((sl_uchar *)mp->b_rptr)[2] = (len-3<64?len-3:63); }#if 0 ptrace(("tx: bsn=%x, bib=%x, fsn=%x, fib=%x, len=%d, sio=%d\n", sl->statem.tx.N.bsn, sl->statem.tx.N.bib, sl->statem.tx.N.fsn, sl->statem.tx.N.fib, len, 0 ));#endif sl->dcalls->daedt_xmit(sl, mp); }}/* * ----------------------------------------------------------------------- * * STATE MACHINES:- The order of the state machine primitives below may seem * somewhat disorganized at first glance; however, they have been ordered by * dependency because they are all inline functions. You see, the L2 state * machine does not required multiple threading because there is never a * requirement to invoke the individual state machines concurrently. This * works out good for the driver, because a primitive action expands inline * to the necessary procedure, while the source still takes the appearance of * the SDL diagrams in the SS7 specification for inspection and debugging. * * ----------------------------------------------------------------------- */#define sl_cc_stop sl_cc_normalstatic inline void sl_cc_normal(sl_t *sl) { sl_timer_stop(t5); sl->statem.cc_state = SL_STATE_IDLE;}static inline void sl_rc_stop(sl_t *sl) { sl_cc_normal(sl); sl->statem.rc_state = SL_STATE_IDLE;}static inline void sl_iac_stop(sl_t *sl) { if ( sl->statem.iac_state != SL_STATE_IDLE ) { sl_timer_stop(t3); sl_timer_stop(t2); sl_timer_stop(t4); sl->dcalls->aerm_stop(sl); sl->statem.emergency = 0; sl->statem.iac_state = SL_STATE_IDLE; }}static void sl_txc_transmission_request(sl_t *sl);static inline void sl_daedt_transmitter_wakeup(sl_t *sl) { if ( sl->statem.txc_state == SL_STATE_SLEEPING ) { sl->statem.txc_state = SL_STATE_IN_SERVICE; sl_txc_transmission_request(sl); }}static inline void sl_txc_send_sios(sl_t *sl) { sl_timer_stop(t7); if ( sl->option.pvar == SS7_PVAR_ANSI_92 ) sl_timer_stop(t6); sl->statem.lssu_available = 1; sl->statem.tx.sio = LSSU_SIOS; sl_daedt_transmitter_wakeup(sl);}static inline void sl_poc_stop(sl_t* sl){ sl->statem.poc_state = SL_STATE_IDLE;}static inline void sl_lsc_link_failure(sl_t *sl) { if ( sl->statem.lsc_state != SL_STATE_OUT_OF_SERVICE ) { sl_l3_out_of_service(sl, sl->statem.failure_reason); sl_iac_stop(sl); /* ok if not aligning */ sl_timer_stop(t1); /* ok if not running */ sl->dcalls->suerm_stop(sl); /* ok if not running */ sl_rc_stop(sl); sl_txc_send_sios(sl); sl_poc_stop(sl); /* ok if not ITUT */ sl->statem.emergency = 0; sl->statem.local_processor_outage = 0; sl->statem.remote_processor_outage = 0; /* ok if not ANSI */ sl->statem.lsc_state = SL_STATE_OUT_OF_SERVICE; }}static void sl_t6_timeout(sl_t *sl) { sl->statem.failure_reason = SL_FAIL_CONG_TIMEOUT; sl_lsc_link_failure(sl); sl->statem.sib_received = 0; sl_timer_stop(t7);}static void sl_t7_timeout(sl_t *sl) { sl->statem.failure_reason = SL_FAIL_ACK_TIMEOUT; sl_lsc_link_failure(sl); sl_timer_stop(t6); if ( sl->option.pvar == SS7_PVAR_ITUT_96 ) sl->statem.sib_received = 0;}static inline void sl_txc_send_sib(sl_t *sl) { sl->statem.lssu_available = 1; sl->statem.tx.sio = LSSU_SIB; sl_daedt_transmitter_wakeup(sl);}static inline void sl_txc_send_sipo(sl_t *sl) { sl_timer_stop(t7); if ( sl->option.pvar == SS7_PVAR_ANSI_92 ) sl_timer_stop(t6); sl->statem.lssu_available = 1; sl->statem.tx.sio = LSSU_SIPO; sl_daedt_transmitter_wakeup(sl);}static inline void sl_txc_send_sio(sl_t *sl) { sl->statem.lssu_available = 1; sl->statem.tx.sio = LSSU_SIO; sl_daedt_transmitter_wakeup(sl);}static inline void sl_txc_send_sin(sl_t *sl) { sl->statem.lssu_available = 1; sl->statem.tx.sio = LSSU_SIN; sl_daedt_transmitter_wakeup(sl);}static inline void sl_txc_send_sie(sl_t *sl) { sl->statem.lssu_available = 1; sl->statem.tx.sio = LSSU_SIE; sl_daedt_transmitter_wakeup(sl);}static inline void sl_txc_send_msu(sl_t *sl) { if ( sl->rtb.q_count ) sl_timer_start(t7); sl->statem.msu_inhibited = 0; sl->statem.lssu_available = 0; sl_daedt_transmitter_wakeup(sl);}static inline void sl_txc_send_fisu(sl_t *sl) { sl_timer_stop(t7); if ( sl->option.pvar == SS7_PVAR_ANSI_92 && !(sl->option.popt & SS7_POPT_PCR) ) sl_timer_stop(t6); sl->statem.msu_inhibited = 1; sl->statem.lssu_available = 0; sl_daedt_transmitter_wakeup(sl);}static inline void sl_txc_fsnx_value(sl_t *sl) { if ( sl->statem.tx.X.fsn != sl->statem.rx.X.fsn ) { sl->statem.tx.X.fsn = sl->statem.rx.X.fsn; sl_daedt_transmitter_wakeup(sl); }}static inline void sl_txc_nack_to_be_sent(sl_t *sl) { sl->statem.tx.N.bib = sl->statem.tx.N.bib ?0:sl->statem.ib_mask; sl_daedt_transmitter_wakeup(sl);}static inline void sl_lsc_rtb_cleared(sl_t *sl) { if ( sl->statem.lsc_state == SL_STATE_PROCESSOR_OUTAGE ) { sl->statem.remote_processor_outage = 0; if ( sl->statem.local_processor_outage ) return; sl_l3_remote_processor_recovered(sl); sl_l3_rtb_cleared(sl); sl_txc_send_msu(sl); sl->statem.lsc_state = SL_STATE_IN_SERVICE; }}static void sl_check_congestion(sl_t *sl);static inline void sl_txc_bsnr_and_bibr(sl_t *sl) { int pcr = sl->option.popt & SS7_POPT_PCR; sl->statem.tx.R.bsn = sl->statem.rx.R.bsn; sl->statem.tx.R.bib = sl->statem.rx.R.bib; if ( sl->statem.clear_rtb ) { bufq_purge(&sl->rtb); sl->statem.Ct = 0; sl_check_congestion(sl); sl->statem.tx.F.fsn = (sl->statem.tx.R.bsn +1)&sl->statem.sn_mask; sl->statem.tx.L.fsn = sl->statem.tx.R.bsn; sl->statem.tx.N.fsn = sl->statem.tx.R.bsn; sl->statem.tx.N.fib = sl->statem.tx.R.bib; sl->statem.Z = (sl->statem.tx.R.bsn +1)&sl->statem.sn_mask; sl->statem.z_ptr = NULL; sl_lsc_rtb_cleared(sl); sl->statem.clear_rtb = 0; sl->statem.rtb_full = 0; return; } if ( sl->statem.tx.F.fsn != ((sl->statem.tx.R.bsn +1)&sl->statem.sn_mask) ) { if ( sl->statem.sib_received ) { sl->statem.sib_received = 0; sl_timer_stop(t6); } do { freemsg(bufq_dequeue(&sl->rtb)); sl->statem.Ct--; sl->statem.tx.F.fsn = (sl->statem.tx.F.fsn +1)&sl->statem.sn_mask; } while ( sl->statem.tx.F.fsn != ((sl->statem.tx.R.bsn +1)&sl->statem.sn_mask) ); sl_check_congestion(sl); sl_daedt_transmitter_wakeup(sl); if ( sl->rtb.q_count == 0 ) { sl_timer_stop(t7); } else { sl_timer_start(t7); } if ( !pcr || ( sl->rtb.q_msgs < sl->config.N1 && sl->rtb.q_count < sl->config.N2 ) ) sl->statem.rtb_full = 0; if ( SN_OUTSIDE(sl->statem.tx.F.fsn, sl->statem.Z, sl->statem.tx.L.fsn) || !sl->rtb.q_count) { sl->statem.Z = sl->statem.tx.F.fsn; sl->statem.z_ptr = sl->rtb.q_head; } } if ( pcr ) return; if ( sl->statem.tx.N.fib != sl->statem.tx.R.bib ) { if ( sl->statem.sib_received ) { sl->statem.sib_received = 0; sl_timer_stop(t6); } sl->statem.tx.N.fib = sl->statem.tx.R.bib; sl->statem.tx.N.fsn = (sl->statem.tx.F.fsn -1)&sl->statem.sn_mask; if ( (sl->statem.z_ptr = sl->rtb.q_head) != NULL ) sl->statem.retrans_cycle = 1; sl_daedt_transmitter_wakeup(sl); return; }}static inline void sl_txc_sib_received(sl_t *sl){ /* FIXME: consider these variations for all */ if ( sl->option.pvar == SS7_PVAR_ANSI_92 && sl->statem.lssu_available ) if ( sl->statem.tx.sio != LSSU_SIB ) return; if ( sl->option.pvar != SS7_PVAR_ITUT_93 && !sl->rtb.q_count ) return; if ( ! sl->statem.sib_received ) { sl_timer_start(t6); sl->statem.sib_received = 1; } sl_timer_start(t7);}static inline void sl_txc_clear_rtb(sl_t *sl) { bufq_purge(&sl->rtb); sl->statem.Ct = 0; sl->statem.clear_rtb = 1; 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(sl);}static inline void sl_txc_clear_tb(sl_t *sl) { bufq_purge(&sl->tb); sl->statem.Cm = 0; sl_check_congestion(sl);}static inline void sl_txc_flush_buffers(sl_t *sl){ bufq_purge(&sl->rtb); sl->statem.Ct = 0; bufq_purge(&sl->tb); sl->statem.rtb_full = 0; sl->statem.Cm = 0; sl->statem.Z = 0; sl->statem.z_ptr = NULL; /* Z =0 error in ITUT 93 and ANSI */ sl->statem.Z = sl->statem.tx.F.fsn = (sl->statem.tx.R.bsn +1)&sl->statem.sn_mask; sl->statem.tx.L.fsn = sl->statem.rx.R.bsn; sl->statem.rx.T.fsn = sl->statem.rx.R.bsn; sl_timer_stop(t7); return;}static inline void sl_rc_fsnt_value(sl_t *sl) { sl->statem.rx.T.fsn = sl->statem.tx.N.fsn;}static inline void sl_txc_retrieval_request_and_fsnc(sl_t *sl, sl_ulong fsnc){ mblk_t *mp; sl->statem.tx.C.fsn = fsnc & (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 ( sl->rtb.q_count && sl->statem.tx.F.fsn != ((fsnc +1)&sl->statem.sn_mask) ) { freemsg(bufq_dequeue(&sl->rtb)); sl->statem.Ct--; sl->statem.tx.F.fsn = (sl->statem.tx.F.fsn +1)&sl->statem.sn_mask; } while ( (mp = bufq_dequeue(&sl->tb)) ) { sl->statem.Cm--; bufq_queue(&sl->rtb, mp); sl->statem.Ct++; } sl->statem.Z = sl->statem.tx.F.fsn = (sl->statem.tx.C.fsn +1)&sl->statem.sn_mask; while ( (mp = bufq_dequeue(&sl->rtb)) ) { sl->statem.Ct--; sl_l3_retrieved_message(sl, mp); } sl->statem.rtb_full = 0; sl_l3_retrieval_complete(sl); sl->statem.Cm = 0; sl->statem.Ct = 0; sl->statem.tx.N.fsn = sl->statem.tx.L.fsn = sl->statem.tx.C.fsn;}static void sl_txc_transmission_request(sl_t *sl) { int pcr; if ( sl->statem.txc_state != SL_STATE_IN_SERVICE ) return; pcr = sl->option.popt & SS7_POPT_PCR; if ( sl->statem.lssu_available ) { if ( sl->statem.tx.sio == LSSU_SIB ) sl->statem.lssu_available = 0; sl->statem.tx.N.fsn = sl->statem.tx.L.fsn; /* sl->statem.tx.N.bib = sl->statem.tx.N.bib; */ sl->statem.tx.N.bsn = (sl->statem.tx.X.fsn - 1)&sl->statem.sn_mask; /* sl->statem.tx.N.fib = sl->statem.tx.N.fib; */ sl_daedt_lssu(sl); return; } if ( sl->statem.msu_inhibited ) { sl->statem.tx.N.fsn = sl->statem.tx.L.fsn; /* sl->statem.tx.N.bib = sl->statem.tx.N.bib; */ sl->statem.tx.N.bsn = (sl->statem.tx.X.fsn - 1)&sl->statem.sn_mask; /* sl->statem.tx.N.fib = sl->statem.tx.N.fib; */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -