⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdt.c

📁 OpenSS7 This the fourth public release of the OpenSS7 Master Package. See README in the release for
💻 C
📖 第 1 页 / 共 5 页
字号:
 *  ------------------------------------------------------------------------- * *  State Machine * *  ------------------------------------------------------------------------- */STATIC INLINE intsdt_aerm_su_in_error(queue_t *q, struct sdt *s){	int err;	if (s->statem.aerm_state == SDT_STATE_MONITORING) {		s->statem.Ca++;		if (s->statem.Ca == s->statem.Ti) {			s->statem.aborted_proving = 1;			if ((err = sdt_iac_abort_proving_ind(q, s))) {				s->statem.Ca--;				return (err);			}			s->statem.aerm_state = SDT_STATE_IDLE;		}	}	return (QR_DONE);}STATIC INLINE intsdt_aerm_correct_su(queue_t *q, struct sdt *s){	int err;	if (s->statem.aerm_state == SDT_STATE_IDLE) {		if (s->statem.aborted_proving) {			if ((err = sdt_iac_correct_su_ind(q, s)))				return (err);			s->statem.aborted_proving = 0;		}	}	return (QR_DONE);}STATIC INLINE intsdt_suerm_start(queue_t *q, struct sdt *s){	s->statem.Cs = 0;	s->statem.Ns = 0;	s->statem.suerm_state = SDT_STATE_IN_SERVICE;	return (QR_DONE);}STATIC INLINE voidsdt_suerm_stop(queue_t *q, struct sdt *s){	s->statem.suerm_state = SDT_STATE_IDLE;}STATIC INLINE intsdt_suerm_su_in_error(queue_t *q, struct sdt *s){	int err;	if (s->statem.suerm_state == SDT_STATE_IN_SERVICE) {		s->statem.Cs++;		if (s->statem.Cs >= s->config.T) {			if ((err = sdt_lsc_link_failure_ind(q, s))) {				s->statem.Ca--;				return (err);			}			s->statem.suerm_state = SDT_STATE_IDLE;			return (QR_DONE);		}		s->statem.Ns++;		if (s->statem.Ns >= s->config.D) {			s->statem.Ns = 0;			if (s->statem.Cs)				s->statem.Cs--;		}	}	return (QR_DONE);}STATIC INLINE voidsdt_eim_su_in_error(queue_t *q, struct sdt *s){	if (s->statem.eim_state == SDT_STATE_MONITORING)		s->statem.interval_error = 1;}STATIC INLINE voidsdt_suerm_correct_su(queue_t *q, struct sdt *s){	if (s->statem.suerm_state == SDT_STATE_IN_SERVICE) {		s->statem.Ns++;		if (s->statem.Ns >= s->config.D) {			s->statem.Ns = 0;			if (s->statem.Cs)				s->statem.Cs--;		}	}}STATIC INLINE voidsdt_eim_correct_su(queue_t *q, struct sdt *s){	if (s->statem.eim_state == SDT_STATE_MONITORING)		s->statem.su_received = 1;}STATIC INLINE intsdt_eim_start(queue_t *q, struct sdt *s){	s->statem.Ce = 0;	s->statem.interval_error = 0;	s->statem.su_received = 0;	sdt_timer_start(s, t8);	s->statem.eim_state = SDT_STATE_MONITORING;	return (QR_DONE);}STATIC INLINE voidsdt_eim_stop(queue_t *q, struct sdt *s){	s->statem.eim_state = SDT_STATE_IDLE;	sdt_timer_stop(s, t8);}STATIC INLINE intsdt_daedr_correct_su(queue_t *q, struct sdt *s){	sdt_eim_correct_su(q, s);	sdt_suerm_correct_su(q, s);	return sdt_aerm_correct_su(q, s);}STATIC INLINE intsdt_daedr_su_in_error(queue_t *q, struct sdt *s){	int err;	sdt_eim_su_in_error(q, s);	if ((err = sdt_suerm_su_in_error(q, s)))		return (err);	if ((err = sdt_aerm_su_in_error(q, s)))		return (err);	return (QR_DONE);}STATIC INLINE intsdt_daedr_received_bits(queue_t *q, struct sdt *s, mblk_t *mp){	sdt_path_t *rx = &s->rx;	int err, pos, match = 0, len = msgdsize(mp);	int hlen = (s->option.popt & SS7_POPT_XSN) ? 6 : 3;	if (rx->cmp) {		if (len < hlen + 3 && len >= hlen && len == msgdsize(rx->cmp))			for (match = 1, pos = 0; pos < len; pos++)				if (!(match = (mp->b_rptr[pos] == rx->cmp->b_rptr[pos])))					break;		if (match) {			rx->repeat++;			s->stats.rx_sus_compressed++;			freemsg(mp);			sdt_daedr_correct_su(q, s);			return (QR_ABSORBED);		} else if (rx->repeat > 0			   && (err =			       sdt_rc_signal_unit_ind(q, s, xchg(&rx->cmp, NULL),						      xchg(&rx->repeat, 0))) != QR_ABSORBED)			goto overflow;	}	if (!match && len < hlen + 3 && (rx->cmp || (rx->cmp = allocb(len, BPRI_MED)))) {		bcopy(mp->b_rptr, rx->cmp->b_rptr, len);		rx->cmp->b_wptr = rx->cmp->b_rptr + len;		rx->repeat = 0;	}	sdt_daedr_correct_su(q, s);	if ((err = sdt_rc_signal_unit_ind(q, s, mp, 1)) == QR_ABSORBED)		return (QR_ABSORBED);      overflow:	s->stats.rx_buffer_overflows++;	return (err);}#if 0STATIC INLINE intsdt_daedt_transmission_request(queue_t *q, struct sdt *s){	return sdt_txc_transmission_request_ind(q, s);}#endif/* *  ======================================================================== * *  Soft-HDLC * *  ======================================================================== */#define SDT_TX_STATES	5#define SDT_RX_STATES	14#define SDT_TX_BUFSIZE	PAGE_SIZE#define SDT_RX_BUFSIZE	PAGE_SIZE#define SDT_CRC_TABLE_LENGTH	512#define SDT_TX_TABLE_LENGTH	(2* SDT_TX_STATES * 256)#define SDT_RX_TABLE_LENGTH	(2* SDT_RX_STATES * 256)struct tx_entry __attribute__ ((packed));typedef struct tx_entry {	uint bit_string:10;		/* the output string */	uint bit_length:4;		/* length in excess of 8 bits of output string */	uint state:3;			/* new state */} tx_entry_t;struct rx_entry __attribute__ ((packed));typedef struct rx_entry {	uint bit_string:16;	uint bit_length:4;	uint state:4;	uint sync:1;	uint hunt:1;	uint flag:1;	uint idle:1;} rx_entry_t;typedef uint16_t bc_entry_t;STATIC bc_entry_t *bc_table = NULL;STATIC tx_entry_t *tx_table = NULL;STATIC rx_entry_t *rx_table = NULL;// STATIC rx_entry_t *rx_table7 = NULL;STATIC size_t bc_order = 0;STATIC size_t tx_order = 0;STATIC size_t rx_order = 0;STATIC INLINE tx_entry_t *tx_index8(uint j, uint k){	return &tx_table[(j << 8) | k];}#if 0STATIC INLINE rx_entry_t *rx_index7(uint j, uint k){	return &rx_table7[(j << 8) | k];}#endifSTATIC INLINE rx_entry_t *rx_index8(uint j, uint k){	return &rx_table[(j << 8) | k];}#ifdef _DEBUG#if 0STATIC INLINE voidprintb(uint8_t byte){	uint8_t mask = 0x80;	while (mask) {		if (mask & byte)			printd(("1"));		else			printd(("0"));	}}STATIC INLINE voidprintbs(uint str, uint len){	uint mask = (1 << len);	while (mask >>= 1) {		if (mask & str)			printd(("1"));		else			printd(("0"));	}}STATIC INLINE voidprintr(rx_entry_t * r){	printd(("rx(%2d) %d%d%d%d ", r->state, r->flag, r->sync, r->hunt, r->idle));	printbs(r->bit_string, r->bit_length);	printd(("\n"));}STATIC INLINE voidprintt(tx_entry_t * t){	printd(("tx(%2d) ", t->state));	printbs(t->bit_string, t->bit_length + 8);	printd(("\n"));}#endif#elseSTATIC INLINE voidprintb(uint8_t byte){}STATIC INLINE voidprintr(rx_entry_t * r){}STATIC INLINE voidprintt(tx_entry_t * t){}#endif/* *  TX REPEAT *  ---------------------------------------- *  Set up the FISU/LSSU repeat buffer for a new message for transmission. * *  We need to set up the repeat buffer with every new message.  The repeat *  buffer contains a FISU for transmitted MSUs (if non-PCR).  It contains the *  FISU, LSSU or 2-byte LSSU for transmitted FISUs and LSSUs.  For SIBs it *  contains a FISU (if non-PCR), for other LSSUs it contains the LSSU. */STATIC intsdt_tx_repeat(queue_t *q, struct sdt *s, mblk_t *mp){	mblk_t *cp;	int len, hlen, clen;	if ((len = msgdsize(mp)) < (hlen = (s->option.popt & SS7_POPT_XSN) ? 6 : 3)) {		ptrace(("%s: %p: ERROR: user violated minimum size\n", MOD_NAME, s));		goto dont_repeat;	}	if (len > hlen + 2	    || ((len == hlen + 1 || len == hlen + 2) && (mp->b_rptr[hlen] & 0x7) == 5)) {		/* 		   MSU or SIB */		if (s->option.popt & SS7_POPT_PCR)			goto dont_repeat;		clen = hlen;	} else {		/* 		   FISU or LSSU */		clen = len;	}	if (!(cp = s->tx.cmp) && !(cp = s->tx.cmp = ss7_allocb(q, clen, BPRI_MED)))		return (-ENOBUFS);	bcopy(mp->b_rptr, cp->b_rptr, clen);	cp->b_wptr = cp->b_rptr + clen;	if (!(s->option.popt & SS7_POPT_XSN))		((uint8_t *) cp->b_rptr)[2] = clen - hlen;	else		((uint16_t *) cp->b_rptr)[2] = clen - hlen;	return (0);      dont_repeat:	if (s->tx.cmp)		freemsg(xchg(&s->tx.cmp, NULL));	return (0);}/* *  TX BUFFER *  ---------------------------------------- *  Pick up another TX buffer from the queue or a repeat frame. */STATIC mblk_t *sdt_tx_buffer(queue_t *q, struct sdt *s){	mblk_t *dp = NULL;	psw_t flags;	/* 	   lock down while we traverse queue */	spin_lock_irqsave(&s->qlock, flags);	{		mblk_t *mp;		for (mp = s->iq->q_first; mp; mp = mp->b_next) {			switch (mp->b_datap->db_type) {			case M_DATA:				if (sdt_tx_repeat == 0) {					dp = mp;					rmvq(s->iq, dp);				}				break;			case M_PROTO:				if (*((ulong *) mp->b_rptr) != SDT_DAEDT_TRANSMISSION_REQ)					continue;				if (sdt_tx_repeat == 0) {					dp = mp->b_cont;					rmvq(s->iq, mp);					freeb(mp);				}				break;			default:				continue;			}			break;		}	}	spin_unlock_irqrestore(&s->qlock, flags);	if (!dp && (dp = s->tx.cmp)) {		fixme(("Peg some stats\n"));	}	return (dp);}/* *  TX BITSTUFF *  ---------------------------------------- *  Bitstuff an octet and shift residue for output. */STATIC INLINE voidsdt_tx_bitstuff(sdt_path_t * tx, unsigned char byte){	tx_entry_t *t = tx_index8(tx->state, byte);	tx->state = t->state;	tx->residue |= t->bit_string << tx->rbits;	tx->rbits += t->bit_length + 8;}#define TX_MODE_IDLE	0	/* generating mark idle */#define TX_MODE_FLAG	1	/* generating flag idle */#define TX_MODE_BOF	2	/* generating bof flag */#define TX_MODE_MOF	3	/* generating frames */#define TX_MODE_BCC	4	/* generating bcc bytes *//* *  TX BLOCK *  ---------------------------------------- *  Generate blocks for transmission.  We generate entire transmit blocks.  If *  there are not sufficient messages to build the transmit blocks we will *  repeat FISU/LSSU or idle flags. */STATIC voidsdt_tx_block(queue_t *q, struct sdt *s){	mblk_t *bp;	register sdt_path_t *tx = &s->tx;	sdt_stats_t *stats = &s->stats;#if 0	int bits = (s->config.iftype == SDL_TYPE_DS0A) ? 7 : 8;#else	const int bits = 8;#endif	while (canputnext(s->iq)) {		if (!(bp = ss7_allocb(q, s->config.b, BPRI_MED)))			break;	/* bufcall will bring us back */		if (tx->mode == TX_MODE_IDLE || tx->mode == TX_MODE_FLAG) {			if (!tx->nxt) {			      next_message:				if (tx->msg && tx->msg != tx->cmp)					freemsg(tx->msg);				if ((tx->msg = tx->nxt = sdt_tx_buffer(q, s)))					tx->mode = TX_MODE_BOF;			}		}		/* 		   check if transmission block complete */		while (bp->b_wptr < bp->b_rptr + s->config.b) {			/* 			   drain residue bits, if necessary */			if (tx->rbits >= bits) {			      drain_rbits:				/* 				   drain residue bits */				if (bits == 8)					*bp->b_wptr++ = tx->residue;				else					*bp->b_wptr++ = tx->residue & 0x7f;				tx->residue >>= bits;				tx->rbits -= bits;				continue;			}			switch (tx->mode) {			case TX_MODE_IDLE:				/* 				   mark idle */				tx->residue |= 0xff << tx->rbits;				tx->rbits += 8;				goto drain_rbits;			case TX_MODE_FLAG:				/* 				   idle flags */				tx->residue |= 0x7e << tx->rbits;				tx->rbits += 8;				goto drain_rbits;			case TX_MODE_BOF:				/* 				   add opening flag (also closing flag) */				switch (s->config.f) {				case SDT_FLAGS_ONE:					tx->residue |= 0x7e << tx->rbits;					tx->rbits += 8;					break;				case SDT_FLAGS_SHARED:					tx->residue |= 0x3f7e << tx->rbits;					tx->rbits += 15;					break;				case SDT_FLAGS_TWO:					tx->residue |= 0x7e7e << tx->rbits;					tx->rbits += 16;					break;				default:				case SDT_FLAGS_THREE:					tx->residue |= 0x7e7e7e << tx->rbits;					tx->rbits += 24;					break;				}				tx->state = 0;				tx->bcc = 0x00ff;				tx->mode = TX_MODE_MOF;				goto drain_rbits;			case TX_MODE_MOF:	/* transmit frame bytes */				if (tx->nxt->b_rptr < tx->nxt->b_wptr				    || (tx->nxt = tx->nxt->b_cont)) {					/* 					   continuing in message */					uint byte = *(tx->nxt->b_rptr)++;					tx->bcc =					    (tx->bcc >> 8) ^ bc_table[(tx->bcc ^ byte) & 0x00ff];					sdt_tx_bitstuff(tx, byte);					stats->tx_bytes++;				} else {					/* 					   finished message: add 1st bcc byte */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -