📄 sdt.c
字号:
sdt_tx_bitstuff(tx, tx->bcc & 0x00ff); tx->mode = TX_MODE_BCC; } goto drain_rbits; case TX_MODE_BCC: /* add 2nd bcc byte */ sdt_tx_bitstuff(tx, tx->bcc >> 8); stats->tx_sus++; tx->mode = TX_MODE_FLAG; goto next_message; } swerr(); } putnext(q, bp); }}#if 0/* * RX COMPRESS * ---------------------------------------- * Check for RX compression. Returns 1 when compression in effect, 0 * otherwise. */STATIC INLINE intsdt_rx_compress(queue_t *q, struct sdt *s, mblk_t *mp){ mblk_t *cp = s->rx.cmp; int len1 = msgdsize(mp); int len2 = cp ? msgdsize(cp) : 0; int len_max = (s->option.popt & SS7_POPT_XSN) ? 8 : 5; if (len1 > len_max) { // printd(("sdt: len1 = %d > len_max = %d\n", len1, len_max)); goto failure; } if (len1 != len2) { // printd(("sdt: len1 = %d != len2 = %d\n", len1, len2)); goto failure; } else { int pos; // pullupmsg(mp, len1); for (pos = 0; pos < len1; pos++) if (cp->b_rptr[pos] != mp->b_rptr[pos]) { // printd(("sdt: mismatch at byte %d\n", pos + 1)); goto failure; } return (1); } failure: return (0);}#endif/* * RX LINKB * ---------------------------------------- * Link a buffer to existing message or create new message with buffer. */STATIC INLINE voidsdt_rx_linkb(sdt_path_t * rx){ if (rx->msg) linkb(rx->msg, rx->nxt); else rx->msg = rx->nxt; rx->nxt = NULL; return;}#define RX_MODE_HUNT 0 /* hunting for flags */#define RX_MODE_SYNC 1 /* between frames */#define RX_MODE_MOF 2 /* middle of frame *//* * RX BLOCK * ---------------------------------------- * Process a receive block for a channel or span. We process all of the * octets in the receive block. Any complete messages will be delivered to * the upper layer if the upper layer is not congested. If the upper layer * is congested we discard the message and indicate receive congestion. The * upper layer should be sensitive to its receive queue backlog and start * sending SIB when required. We do not use backenabling from the upper * layer. We merely start discarding complete messages when the upper layer * is congested. */STATIC voidsdt_rx_block(queue_t *q, struct sdt *s, mblk_t *dp){ register sdt_path_t *rx = &s->rx; sdt_stats_t *stats = &s->stats; while (dp->b_rptr < dp->b_wptr) { rx_entry_t *r;#if 0 if (s->config.iftype != SDL_TYPE_DS0A)#endif r = rx_index8(rx->state, *dp->b_rptr++);#if 0 else r = rx_index7(rx->state, *dp->b_rptr++);#endif rx->state = r->state; switch (rx->mode) { case RX_MODE_MOF: if (!r->sync && r->bit_length) { rx->residue |= r->bit_string << rx->rbits; rx->rbits += r->bit_length; } if (!r->flag) { if (r->hunt || r->idle) goto aborted; while (rx->rbits > 16) { if (rx->nxt && rx->nxt->b_wptr >= rx->nxt->b_datap->db_lim) sdt_rx_linkb(rx); if (!rx->nxt && !(rx->nxt = allocb(FASTBUF, BPRI_HI))) goto buffer_overflow; rx->bcc = (rx->bcc >> 8) ^ bc_table[(rx->bcc ^ rx->residue) & 0x00ff]; *(rx->nxt->b_wptr)++ = rx->residue; stats->rx_bytes++; rx->residue >>= 8; rx->rbits -= 8; rx->bytes++; if (!(s->option.popt & SS7_POPT_XSN)) { if (rx->bytes > s->config.m + 1 + 3) goto frame_too_long; } else { if (rx->bytes > s->config.m + 1 + 6) goto frame_too_long; } } } else { uint li; if (rx->rbits != 16) goto residue_error; if (rx->bcc != (rx->residue & 0xffff)) goto crc_error; if (!(s->option.popt & SS7_POPT_XSN)) { if (rx->bytes < 3) goto frame_too_short; sdt_rx_linkb(rx); li = (rx->msg->b_rptr[2] & 0x3f) + 3; if (rx->bytes != li && (li != 0x3f + 3 || rx->bytes < li)) goto length_error; } else { if (rx->bytes < 6) goto frame_too_short; sdt_rx_linkb(rx); li = (((rx->msg->b_rptr[5] << 8) | rx->msg->b_rptr[4]) & 0x1ff) + 6; if (rx->bytes != li && (li != 0x1ff + 6 || rx->bytes < li)) goto length_error; } stats->rx_sus++; sdt_daedr_received_bits(q, s, xchg(&rx->msg, NULL)); new_frame: rx->mode = RX_MODE_SYNC; if (r->sync) { begin_frame: if (r->bit_length) { rx->mode = RX_MODE_MOF; rx->residue = r->bit_string; rx->rbits = r->bit_length; rx->bytes = 0; rx->bcc = 0x00ff; } } } break; frame_too_long: stats->rx_frame_too_long++; stats->rx_frame_errors++; goto abort_frame; buffer_overflow: stats->rx_buffer_overflows++; goto abort_frame; aborted: stats->rx_aborts++; stats->rx_frame_errors++; goto abort_frame; length_error: stats->rx_length_error++; goto abort_frame; frame_too_short: stats->rx_frame_too_short++; stats->rx_frame_errors++; goto abort_frame; crc_error: stats->rx_crc_errors++; goto abort_frame; residue_error: stats->rx_residue_errors++; stats->rx_frame_errors++; goto abort_frame; abort_frame: if (rx->nxt) freemsg(xchg(&rx->nxt, NULL)); if (rx->msg) freemsg(xchg(&rx->msg, NULL)); stats->rx_sus_in_error++; sdt_daedr_su_in_error(q, s); if (r->flag) goto new_frame; rx->mode = RX_MODE_HUNT; stats->rx_sync_transitions++; s->rx_octets = 0; break; case RX_MODE_SYNC: if (!r->hunt && !r->idle) goto begin_frame; rx->mode = RX_MODE_HUNT; stats->rx_sync_transitions++; s->rx_octets = 0; break; case RX_MODE_HUNT: if (!r->flag) { if ((++(s->rx_octets)) >= s->config.N) { stats->rx_sus_in_error++; sdt_daedr_su_in_error(q, s); s->rx_octets -= s->config.N; } stats->rx_bits_octet_counted += 8; break; } stats->rx_sync_transitions++; goto new_frame; default: swerr(); goto abort_frame; } }}/* * ------------------------------------------------------------------------- * * Table allocation and generation * * ------------------------------------------------------------------------- * All Soft HDLC lookup stables are generated at module load time. This * permits the tables to be page-aligned in kernel memory for maximum cache * performance. *//* * BC (Block Check) CRC Table Entries: * ----------------------------------- * RC tables perform CRC calculation on received bits after zero deletion and * delimitation. */STATIC bc_entry_tbc_table_value(int bit_string, int bit_length){ int pos; for (pos = 0; pos < bit_length; pos++) { if (bit_string & 0x1) bit_string = (bit_string >> 1) ^ 0x8408; else bit_string >>= 1; } return (bit_string);}/* * TX (Transmission) Table Entries: * ----------------------------------- * TX table performs zero insertion on frame and CRC bit streams. */STATIC tx_entry_ttx_table_valueN(int state, uint8_t byte, int len){ tx_entry_t result = { 0, }; int bit_mask = 1; result.state = state; result.bit_length = 0; while (len--) { if (byte & 0x1) { result.bit_string |= bit_mask; if (result.state++ == 4) { result.state = 0; result.bit_length++; bit_mask <<= 1; } } else result.state = 0; bit_mask <<= 1; byte >>= 1; } return result;}STATIC tx_entry_ttx_table_value(int state, uint8_t byte){ return tx_table_valueN(state, byte, 8);}/* * RX (Receive) Table Entries: * ----------------------------------- * RX table performs zero deletion, flag and abort detection, BOF and EOF * detection and residue on received bit streams. */STATIC rx_entry_trx_table_valueN(int state, uint8_t byte, int len){ rx_entry_t result = { 0, }; int bit_mask = 1; result.state = state; while (len--) { switch (result.state) { case 0: /* */ if (result.flag && !result.sync) { bit_mask = 1; result.bit_string = 0; result.bit_length = 0; result.sync = 1; } if (byte & 0x1) { result.state = 8; } else { result.state = 1; } break; case 1: /* 0 */ if (byte & 0x1) { result.state = 2; } else { bit_mask <<= 1; result.bit_length += 1; result.state = 1; } break; case 2: /* 01 */ if (byte & 0x1) { result.state = 3; } else { bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_length += 2; result.state = 1; } break; case 3: /* 011 */ if (byte & 0x1) { result.state = 4; } else { bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_length += 3; result.state = 1; } break; case 4: /* 0111 */ if (byte & 0x1) { result.state = 5; } else { bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_length += 4; result.state = 1; } break; case 5: /* 01111 */ if (byte & 0x1) { result.state = 6; } else { bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_length += 5; result.state = 1; } break; case 6: /* 011111 */ if (byte & 0x1) { result.state = 7; } else { bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_length += 6; result.state = 0; } break; case 7: /* 0111111 */ if (byte & 0x1) { result.sync = 0; result.flag = 0; result.hunt = 1; result.state = 12; } else { result.sync = 0; result.flag = 1; result.hunt = 0; result.idle = 0; result.state = 0; } break; case 8: /* 1 */ if (byte & 0x1) { result.state = 9; } else { result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_length += 1; result.state = 1; } break; case 9: /* 11 */ if (byte & 0x1) { result.state = 10; } else { result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_length += 2; result.state = 1; } break; case 10: /* 111 */ if (byte & 0x1) { result.state = 11; } else { result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_length += 3; result.state = 1; } break; case 11: /* 1111 */ if (byte & 0x1) { result.state = 12; } else { result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_length += 4; result.state = 1; } break; case 12: /* 11111 */ if (byte & 0x1) { result.state = 13; } else { result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_string |= bit_mask; bit_mask <<= 1; result.bit_length += 5; result.state = 0; } break; case 13: /* 111111 */ if (byte & 0x1) { result.hunt = 1; result.sync = 0; result.idle = 1; result.flag = 0; result.state = 12; } else { result.sync = 0; result.hunt = 0; result.idle = 0; result.flag = 1; result.state = 0; } break; } byte >>= 1; } return result;}STATIC rx_entry_trx_table_value(int state, uint8_t byte){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -