📄 isdnl2.c
字号:
struct PStack *st = fi->userdata; if (test_bit(FLG_LAPD, &st->l2.flag) && test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) { FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 9); return; } FsmChangeState(fi, ST_L2_8); transmit_enquiry(st); st->l2.rc = 0;}static voidl2_pull_iqueue(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; struct sk_buff *skb, *oskb; struct Layer2 *l2 = &st->l2; u_char header[MAX_HEADER_LEN]; int i; int unsigned p1; u_long flags; if (!cansend(st)) return; skb = skb_dequeue(&l2->i_queue); if (!skb) return; spin_lock_irqsave(&l2->lock, flags); if(test_bit(FLG_MOD128, &l2->flag)) p1 = (l2->vs - l2->va) % 128; else p1 = (l2->vs - l2->va) % 8; p1 = (p1 + l2->sow) % l2->window; if (l2->windowar[p1]) { printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n", p1); dev_kfree_skb(l2->windowar[p1]); } l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC); i = sethdraddr(&st->l2, header, CMD); if (test_bit(FLG_MOD128, &l2->flag)) { header[i++] = l2->vs << 1; header[i++] = l2->vr << 1; l2->vs = (l2->vs + 1) % 128; } else { header[i++] = (l2->vr << 5) | (l2->vs << 1); l2->vs = (l2->vs + 1) % 8; } spin_unlock_irqrestore(&l2->lock, flags); p1 = skb->data - skb->head; if (p1 >= i) memcpy(skb_push(skb, i), header, i); else { printk(KERN_WARNING "isdl2 pull_iqueue skb header(%d/%d) too short\n", i, p1); oskb = skb; skb = alloc_skb(oskb->len + i, GFP_ATOMIC); memcpy(skb_put(skb, i), header, i); memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len); dev_kfree_skb(oskb); } st->l2.l2l1(st, PH_PULL | INDICATION, skb); test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) { FsmDelTimer(&st->l2.t203, 13); FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11); } if (!skb_queue_empty(&l2->i_queue) && cansend(st)) st->l2.l2l1(st, PH_PULL | REQUEST, NULL);}static voidl2_st8_got_super(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; struct sk_buff *skb = arg; int PollFlag, rsp, rnr = 0; unsigned int nr; struct Layer2 *l2 = &st->l2; rsp = *skb->data & 0x2; if (test_bit(FLG_ORIG, &l2->flag)) rsp = !rsp; skb_pull(skb, l2addrsize(l2)); if (IsRNR(skb->data, st)) { set_peer_busy(l2); rnr = 1; } else clear_peer_busy(l2); if (test_bit(FLG_MOD128, &l2->flag)) { PollFlag = (skb->data[1] & 0x1) == 0x1; nr = skb->data[1] >> 1; } else { PollFlag = (skb->data[0] & 0x10); nr = (skb->data[0] >> 5) & 0x7; } dev_kfree_skb(skb); if (rsp && PollFlag) { if (legalnr(st, nr)) { if (rnr) { restart_t200(st, 15); } else { stop_t200(st, 16); FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 5); setva(st, nr); } invoke_retransmission(st, nr); FsmChangeState(fi, ST_L2_7); if (!skb_queue_empty(&l2->i_queue) && cansend(st)) st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } else nrerrorrecovery(fi); } else { if (!rsp && PollFlag) enquiry_response(st); if (legalnr(st, nr)) { setva(st, nr); } else nrerrorrecovery(fi); }}static voidl2_got_FRMR(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; struct sk_buff *skb = arg; skb_pull(skb, l2addrsize(&st->l2) + 1); if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) || /* I or S */ (IsUA(skb->data) && (fi->state == ST_L2_7))) { st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'K'); establishlink(fi); test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); } dev_kfree_skb(skb);}static voidl2_st24_tei_remove(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.ui_queue); st->l2.tei = -1; FsmChangeState(fi, ST_L2_1);}static voidl2_st3_tei_remove(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.ui_queue); st->l2.tei = -1; st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_1);}static voidl2_st5_tei_remove(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.i_queue); skb_queue_purge(&st->l2.ui_queue); freewin(st); st->l2.tei = -1; stop_t200(st, 17); st5_dl_release_l2l3(st); FsmChangeState(fi, ST_L2_1);}static voidl2_st6_tei_remove(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.ui_queue); st->l2.tei = -1; stop_t200(st, 18); st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); FsmChangeState(fi, ST_L2_1);}static voidl2_tei_remove(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.i_queue); skb_queue_purge(&st->l2.ui_queue); freewin(st); st->l2.tei = -1; stop_t200(st, 17); FsmDelTimer(&st->l2.t203, 19); st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_1);}static voidl2_st14_persistant_da(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.i_queue); skb_queue_purge(&st->l2.ui_queue); if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag)) st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);}static voidl2_st5_persistant_da(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.i_queue); skb_queue_purge(&st->l2.ui_queue); freewin(st); stop_t200(st, 19); st5_dl_release_l2l3(st); FsmChangeState(fi, ST_L2_4);}static voidl2_st6_persistant_da(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.ui_queue); stop_t200(st, 20); st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); FsmChangeState(fi, ST_L2_4);}static voidl2_persistant_da(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.i_queue); skb_queue_purge(&st->l2.ui_queue); freewin(st); stop_t200(st, 19); FsmDelTimer(&st->l2.t203, 19); st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_4);}static voidl2_set_own_busy(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; if(!test_and_set_bit(FLG_OWN_BUSY, &st->l2.flag)) { enquiry_cr(st, RNR, RSP, 0); test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); }}static voidl2_clear_own_busy(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; if(!test_and_clear_bit(FLG_OWN_BUSY, &st->l2.flag)) { enquiry_cr(st, RR, RSP, 0); test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); }}static voidl2_frame_error(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; st->ma.layer(st, MDL_ERROR | INDICATION, arg);}static voidl2_frame_error_reest(struct FsmInst *fi, int event, void *arg){ struct PStack *st = fi->userdata; st->ma.layer(st, MDL_ERROR | INDICATION, arg); establishlink(fi); test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);}static struct FsmNode L2FnList[] __initdata ={ {ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign}, {ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3}, {ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish}, {ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3}, {ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish}, {ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish}, {ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release}, {ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel}, {ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect}, {ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect}, {ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest}, {ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull}, {ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue}, {ST_L2_1, EV_L2_DL_UNIT_DATA, l2_queue_ui_assign}, {ST_L2_2, EV_L2_DL_UNIT_DATA, l2_queue_ui}, {ST_L2_3, EV_L2_DL_UNIT_DATA, l2_queue_ui}, {ST_L2_4, EV_L2_DL_UNIT_DATA, l2_send_ui}, {ST_L2_5, EV_L2_DL_UNIT_DATA, l2_send_ui}, {ST_L2_6, EV_L2_DL_UNIT_DATA, l2_send_ui}, {ST_L2_7, EV_L2_DL_UNIT_DATA, l2_send_ui}, {ST_L2_8, EV_L2_DL_UNIT_DATA, l2_send_ui}, {ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei}, {ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei}, {ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei}, {ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove}, {ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove}, {ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove}, {ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove}, {ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove}, {ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove}, {ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove}, {ST_L2_4, EV_L2_SABME, l2_start_multi}, {ST_L2_5, EV_L2_SABME, l2_send_UA}, {ST_L2_6, EV_L2_SABME, l2_send_DM}, {ST_L2_7, EV_L2_SABME, l2_restart_multi}, {ST_L2_8, EV_L2_SABME, l2_restart_multi}, {ST_L2_4, EV_L2_DISC, l2_send_DM}, {ST_L2_5, EV_L2_DISC, l2_send_DM}, {ST_L2_6, EV_L2_DISC, l2_send_UA}, {ST_L2_7, EV_L2_DISC, l2_stop_multi}, {ST_L2_8, EV_L2_DISC, l2_stop_multi}, {ST_L2_4, EV_L2_UA, l2_mdl_error_ua}, {ST_L2_5, EV_L2_UA, l2_connected}, {ST_L2_6, EV_L2_UA, l2_released}, {ST_L2_7, EV_L2_UA, l2_mdl_error_ua}, {ST_L2_8, EV_L2_UA, l2_mdl_error_ua}, {ST_L2_4, EV_L2_DM, l2_reestablish}, {ST_L2_5, EV_L2_DM, l2_st5_dm_release}, {ST_L2_6, EV_L2_DM, l2_st6_dm_release}, {ST_L2_7, EV_L2_DM, l2_mdl_error_dm}, {ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm}, {ST_L2_1, EV_L2_UI, l2_got_ui}, {ST_L2_2, EV_L2_UI, l2_got_ui}, {ST_L2_3, EV_L2_UI, l2_got_ui}, {ST_L2_4, EV_L2_UI, l2_got_ui}, {ST_L2_5, EV_L2_UI, l2_got_ui}, {ST_L2_6, EV_L2_UI, l2_got_ui}, {ST_L2_7, EV_L2_UI, l2_got_ui}, {ST_L2_8, EV_L2_UI, l2_got_ui}, {ST_L2_7, EV_L2_FRMR, l2_got_FRMR}, {ST_L2_8, EV_L2_FRMR, l2_got_FRMR}, {ST_L2_7, EV_L2_SUPER, l2_st7_got_super}, {ST_L2_8, EV_L2_SUPER, l2_st8_got_super}, {ST_L2_7, EV_L2_I, l2_got_iframe}, {ST_L2_8, EV_L2_I, l2_got_iframe}, {ST_L2_5, EV_L2_T200, l2_st5_tout_200}, {ST_L2_6, EV_L2_T200, l2_st6_tout_200}, {ST_L2_7, EV_L2_T200, l2_st7_tout_200}, {ST_L2_8, EV_L2_T200, l2_st8_tout_200}, {ST_L2_7, EV_L2_T203, l2_st7_tout_203}, {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue}, {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, {ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, {ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy}, {ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy}, {ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error}, {ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error}, {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error}, {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest}, {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest}, {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da}, {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove}, {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove}, {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da}, {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da}, {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da}, {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da}, {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},};#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))static voidisdnl2_l1l2(struct PStack *st, int pr, void *arg){ struct sk_buff *skb = arg; u_char *datap; int ret = 1, len; int c = 0; switch (pr) { case (PH_DATA | INDICATION): datap = skb->data; len = l2addrsize(&st->l2); if (skb->len > len) datap += len; else { FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'N'); dev_kfree_skb(skb); return; } if (!(*datap & 1)) { /* I-Frame */ if(!(c = iframe_error(st, skb))) ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb); } else if (IsSFrame(datap, st)) { /* S-Frame */ if(!(c = super_error(st, skb))) ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb); } else if (IsUI(datap)) { if(!(c = UI_error(st, skb))) ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb); } else if (IsSABME(datap, st)) { if(!(c = unnum_error(st, skb, CMD))) ret = FsmEvent(&st->l2.l2m, EV_L2_SABME, skb); } else if (IsUA(datap)) { if(!(c = unnum_error(st, skb, RSP))) ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb); } else if (IsDISC(datap)) { if(!(c = unnum_error(st, skb, CMD))) ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb); } else if (IsDM(datap)) { if(!(c = unnum_error(st, skb, RSP))) ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb); } else if (IsFRMR(datap)) { if(!(c = FRMR_error(st,skb))) ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb); } else { FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'L'); dev_kfree_skb(skb); ret = 0; } if(c) { dev_kfree_skb(skb); FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *)(long)c); ret = 0; } if (ret) dev_kfree_skb(skb); break; case (PH_PULL | CONFIRM): FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg); break; case (PH_PAUSE | INDICATION): test_and_set_bit(FLG_DCHAN_BUSY, &st->l2.flag); break; case (PH_PAUSE | CONFIRM): test_and_clear_bit(FLG_DCHAN_BUSY, &st->l2.flag); break; case (PH_ACTIVATE | CONFIRM): case (PH_ACTIVATE | INDICATION): test_and_set_bit(FLG_L1_ACTIV, &st->l2.flag); if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag)) FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg); break; case (PH_DEACTIVATE | INDICATION): case (PH_DEACTIVATE | CONFIRM): test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag); FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg); break; default: l2m_debug(&st->l2.l2m, "l2 unknown pr %04x", pr); break; }}static voidisdnl2_l3l2(struct PStack *st, int pr, void *arg){ switch (pr) { case (DL_DATA | REQUEST): if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) { dev_kfree_skb((struct sk_buff *) arg); } break; case (DL_UNIT_DATA | REQUEST): if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) { dev_kfree_skb((struct sk_buff *) arg); } break; case (DL_ESTABLISH | REQUEST): if (test_bit(FLG_L1_ACTIV, &st->l2.flag)) { if (test_bit(FLG_LAPD, &st->l2.flag) || test_bit(FLG_ORIG, &st->l2.flag)) { FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg); } } else { if (test_bit(FLG_LAPD, &st->l2.flag) || test_bit(FLG_ORIG, &st->l2.flag)) { test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag); } st->l2.l2l1(st, PH_ACTIVATE, NULL); } break; case (DL_RELEASE | REQUEST): if (test_bit(FLG_LAPB, &st->l2.flag)) { st->l2.l2l1(st, PH_DEACTIVATE, NULL); } FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg); break; case (MDL_ASSIGN | REQUEST): FsmEvent(&st->l2.l2m, EV_L2_MDL_ASSIGN, arg); break; case (MDL_REMOVE | REQUEST): FsmEvent(&st->l2.l2m, EV_L2_MDL_REMOVE, arg); break; case (MDL_ERROR | RESPONSE): FsmEvent(&st->l2.l2m, EV_L2_MDL_ERROR, arg); break; }}voidreleasestack_isdnl2(struct PStack *st){ FsmDelTimer(&st->l2.t200, 21); FsmDelTimer(&st->l2.t203, 16); skb_queue_purge(&st->l2.i_queue); skb_queue_purge(&st->l2.ui_queue); ReleaseWin(&st->l2);}static voidl2m_debug(struct FsmInst *fi, char *fmt, ...){ va_list args; struct PStack *st = fi->userdata; va_start(args, fmt); VHiSax_putstatus(st->l1.hardware, st->l2.debug_id, fmt, args); va_end(args);}voidsetstack_isdnl2(struct PStack *st, char *debug_id){ spin_lock_init(&st->l2.lock); st->l1.l1l2 = isdnl2_l1l2; st->l3.l3l2 = isdnl2_l3l2; skb_queue_head_init(&st->l2.i_queue); skb_queue_head_init(&st->l2.ui_queue); InitWin(&st->l2); st->l2.debug = 0; st->l2.l2m.fsm = &l2fsm; if (test_bit(FLG_LAPB, &st->l2.flag)) st->l2.l2m.state = ST_L2_4; else st->l2.l2m.state = ST_L2_1; st->l2.l2m.debug = 0; st->l2.l2m.userdata = st; st->l2.l2m.userint = 0; st->l2.l2m.printdebug = l2m_debug; strcpy(st->l2.debug_id, debug_id); FsmInitTimer(&st->l2.l2m, &st->l2.t200); FsmInitTimer(&st->l2.l2m, &st->l2.t203);}static voidtransl2_l3l2(struct PStack *st, int pr, void *arg){ switch (pr) { case (DL_DATA | REQUEST): case (DL_UNIT_DATA | REQUEST): st->l2.l2l1(st, PH_DATA | REQUEST, arg); break; case (DL_ESTABLISH | REQUEST): st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); break; case (DL_RELEASE | REQUEST): st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); break; }}voidsetstack_transl2(struct PStack *st){ st->l3.l3l2 = transl2_l3l2;}voidreleasestack_transl2(struct PStack *st){}int __initIsdnl2New(void){ l2fsm.state_count = L2_STATE_COUNT; l2fsm.event_count = L2_EVENT_COUNT; l2fsm.strEvent = strL2Event; l2fsm.strState = strL2State; return FsmNew(&l2fsm, L2FnList, L2_FN_COUNT);}voidIsdnl2Free(void){ FsmFree(&l2fsm);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -