/* * State machine for state 4, Frame Reject State. * The handling of the timer(s) is in file lapb_timer.c. */ static void lapb_state4_machine(struct lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame) { switch (frame->type) { case LAPB_SABM: lapb_dbg(1, "(%p) S4 RX SABM(%d)\n", lapb->dev, frame->pf); if (lapb->mode & LAPB_EXTENDED) { lapb_dbg(1, "(%p) S4 TX DM(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } else { lapb_dbg(1, "(%p) S4 TX UA(%d)\n", lapb->dev, frame->pf); lapb_dbg(0, "(%p) S4 -> S3\n", lapb->dev); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_3; lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_connect_indication(lapb, LAPB_OK); } break; case LAPB_SABME: lapb_dbg(1, "(%p) S4 RX SABME(%d)\n", lapb->dev, frame->pf); if (lapb->mode & LAPB_EXTENDED) { lapb_dbg(1, "(%p) S4 TX UA(%d)\n", lapb->dev, frame->pf); lapb_dbg(0, "(%p) S4 -> S3\n", lapb->dev); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_3; lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_connect_indication(lapb, LAPB_OK); } else { lapb_dbg(1, "(%p) S4 TX DM(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } break; } kfree_skb(skb); }
/* * State machine for state 2, Awaiting Release State. * The handling of the timer(s) is in file lapb_timer.c */ static void lapb_state2_machine(struct lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame) { switch (frame->type) { case LAPB_SABM: case LAPB_SABME: lapb_dbg(1, "(%p) S2 RX {SABM,SABME}(%d)\n", lapb->dev, frame->pf); lapb_dbg(1, "(%p) S2 TX DM(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); break; case LAPB_DISC: lapb_dbg(1, "(%p) S2 RX DISC(%d)\n", lapb->dev, frame->pf); lapb_dbg(1, "(%p) S2 TX UA(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); break; case LAPB_UA: lapb_dbg(1, "(%p) S2 RX UA(%d)\n", lapb->dev, frame->pf); if (frame->pf) { lapb_dbg(0, "(%p) S2 -> S0\n", lapb->dev); lapb->state = LAPB_STATE_0; lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb_disconnect_confirmation(lapb, LAPB_OK); } break; case LAPB_DM: lapb_dbg(1, "(%p) S2 RX DM(%d)\n", lapb->dev, frame->pf); if (frame->pf) { lapb_dbg(0, "(%p) S2 -> S0\n", lapb->dev); lapb->state = LAPB_STATE_0; lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb_disconnect_confirmation(lapb, LAPB_NOTCONNECTED); } break; case LAPB_I: case LAPB_REJ: case LAPB_RNR: case LAPB_RR: lapb_dbg(1, "(%p) S2 RX {I,REJ,RNR,RR}(%d)\n", lapb->dev, frame->pf); lapb_dbg(1, "(%p) S2 RX DM(%d)\n", lapb->dev, frame->pf); if (frame->pf) lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); break; } kfree_skb(skb); }
void lapb_establish_data_link(struct lapb_cb *lapb) { lapb->condition = 0x00; lapb->n2count = 0; if (lapb->mode & LAPB_EXTENDED) { lapb_dbg(1, "(%p) S%d TX SABME(1)\n", lapb->dev, lapb->state); lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { lapb_dbg(1, "(%p) S%d TX SABM(1)\n", lapb->dev, lapb->state); lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); } lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); }
void lapb_timeout_response(struct lapb_cb *lapb) { lapb_dbg(1, "(%p) S%d TX RR(0) R%d\n", lapb->dev, lapb->state, lapb->vr); lapb_send_control(lapb, LAPB_RR, LAPB_POLLOFF, LAPB_RESPONSE); lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; }
int lapb_disconnect_request(void *token) { lapb_cb *lapb; if ((lapb = lapb_tokentostruct(token)) == NULL) return LAPB_BADTOKEN; switch (lapb->state) { case LAPB_STATE_0: return LAPB_NOTCONNECTED; case LAPB_STATE_1: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->token); #endif #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token); #endif lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND); lapb->state = LAPB_STATE_0; lapb_start_t1timer(lapb); return LAPB_NOTCONNECTED; case LAPB_STATE_2: return LAPB_OK; } lapb_clear_queues(lapb); lapb->n2count = 0; lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_2; #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->token); #endif #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S2\n", lapb->token); #endif return LAPB_OK; }
void lapb_timeout_response(struct lapb_cb *lapb) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S%d TX RR(0) R%d\n", lapb->token, lapb->state, lapb->vr); #endif lapb_send_control(lapb, LAPB_RR, LAPB_POLLOFF, LAPB_RESPONSE); lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; }
void lapb_establish_data_link(lapb_cb *lapb) { lapb->condition = 0x00; lapb->n2count = 0; if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S%d TX SABME(1)\n", lapb->token, lapb->state); #endif lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S%d TX SABM(1)\n", lapb->token, lapb->state); #endif lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); } lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); }
/* * State machine for state 2, Awaiting Release State. * The handling of the timer(s) is in file lapb_timer.c */ void lapb_state2_machine(struct lapb_cs * lapb, struct lapb_frame * frame) { //struct lapb_cs_internal * lapb_int = lapb_get_internal(lapb); switch (frame->type) { // case LAPB_SABM: // case LAPB_SABME: // lapb->callbacks->debug(2, "[LAPB] S2 RX {SABM,SABME}(%d)", frame->pf); // lapb->callbacks->debug(2, "[LAPB] S2 TX DM(%d)", frame->pf); // lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); // lapb_reset(lapb, LAPB_STATE_0); // break; case LAPB_DISC: lapb->callbacks->debug(2, "[LAPB] S2 RX DISC(%d)", frame->pf); lapb->callbacks->debug(2, "[LAPB] S2 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); break; case LAPB_UA: lapb->callbacks->debug(2, "[LAPB] S2 RX UA(%d)", frame->pf); lapb_requeue_frames(lapb); lapb_disconnect_confirmation(lapb, LAPB_OK); lapb_reset(lapb, LAPB_STATE_0); break; case LAPB_DM: lapb->callbacks->debug(2, "[LAPB] S2 RX DM(%d)", frame->pf); lapb_requeue_frames(lapb); lapb_disconnect_confirmation(lapb, LAPB_NOTCONNECTED); lapb_reset(lapb, LAPB_STATE_0); break; // case LAPB_I: // case LAPB_REJ: // case LAPB_RNR: // case LAPB_RR: // lapb->callbacks->debug(2, "[LAPB] S2 RX {I,REJ,RNR,RR}(%d)", frame->pf); // lapb->callbacks->debug(2, "[LAPB] S2 TX DM(%d)", frame->pf); // if (frame->pf) // lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); // break; }; }
/* * State machine for state 2, Awaiting Release State. * The handling of the timer(s) is in file lapb_timer.c */ static void lapb_state2_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame) { switch (frame->type) { case LAPB_SABM: case LAPB_SABME: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S2 RX {SABM,SABME}(%d)\n", lapb->token, frame->pf); printk(KERN_DEBUG "lapb: (%p) S2 TX DM(%d)\n", lapb->token, frame->pf); #endif lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); break; case LAPB_DISC: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S2 RX DISC(%d)\n", lapb->token, frame->pf); printk(KERN_DEBUG "lapb: (%p) S2 TX UA(%d)\n", lapb->token, frame->pf); #endif lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); break; case LAPB_UA: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S2 RX UA(%d)\n", lapb->token, frame->pf); #endif if (frame->pf) { #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->token); #endif lapb->state = LAPB_STATE_0; lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb_disconnect_confirmation(lapb, LAPB_OK); } break; case LAPB_DM: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n", lapb->token, frame->pf); #endif if (frame->pf) { #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->token); #endif lapb->state = LAPB_STATE_0; lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb_disconnect_confirmation(lapb, LAPB_NOTCONNECTED); } break; case LAPB_I: case LAPB_REJ: case LAPB_RNR: case LAPB_RR: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S2 RX {I,REJ,RNR,RR}(%d)\n", lapb->token, frame->pf); printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n", lapb->token, frame->pf); #endif if (frame->pf) lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); break; default: break; } kfree_skb(skb); }
/* * State machine for state 3, Connected State. * The handling of the timer(s) is in file lapb_timer.c */ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame) { int queued = 0; int modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS; switch (frame->type) { case LAPB_SABM: lapb_dbg(1, "(%p) S3 RX SABM(%d)\n", lapb->dev, frame->pf); if (lapb->mode & LAPB_EXTENDED) { lapb_dbg(1, "(%p) S3 TX DM(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } else { lapb_dbg(1, "(%p) S3 TX UA(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_requeue_frames(lapb); } break; case LAPB_SABME: lapb_dbg(1, "(%p) S3 RX SABME(%d)\n", lapb->dev, frame->pf); if (lapb->mode & LAPB_EXTENDED) { lapb_dbg(1, "(%p) S3 TX UA(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_requeue_frames(lapb); } else { lapb_dbg(1, "(%p) S3 TX DM(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } break; case LAPB_DISC: lapb_dbg(1, "(%p) S3 RX DISC(%d)\n", lapb->dev, frame->pf); lapb_dbg(0, "(%p) S3 -> S0\n", lapb->dev); lapb_clear_queues(lapb); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_0; lapb_disconnect_indication(lapb, LAPB_OK); break; case LAPB_DM: lapb_dbg(1, "(%p) S3 RX DM(%d)\n", lapb->dev, frame->pf); lapb_dbg(0, "(%p) S3 -> S0\n", lapb->dev); lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED); break; case LAPB_RNR: lapb_dbg(1, "(%p) S3 RX RNR(%d) R%d\n", lapb->dev, frame->pf, frame->nr); lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_RR: lapb_dbg(1, "(%p) S3 RX RR(%d) R%d\n", lapb->dev, frame->pf, frame->nr); lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_REJ: lapb_dbg(1, "(%p) S3 RX REJ(%d) R%d\n", lapb->dev, frame->pf, frame->nr); lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_frames_acked(lapb, frame->nr); lapb_stop_t1timer(lapb); lapb->n2count = 0; lapb_requeue_frames(lapb); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_I: lapb_dbg(1, "(%p) S3 RX I(%d) S%d R%d\n", lapb->dev, frame->pf, frame->ns, frame->nr); if (!lapb_validate_nr(lapb, frame->nr)) { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; break; } if (lapb->condition & LAPB_PEER_RX_BUSY_CONDITION) lapb_frames_acked(lapb, frame->nr); else lapb_check_iframes_acked(lapb, frame->nr); if (frame->ns == lapb->vr) { int cn; cn = lapb_data_indication(lapb, skb); queued = 1; /* * If upper layer has dropped the frame, we * basically ignore any further protocol * processing. This will cause the peer * to re-transmit the frame later like * a frame lost on the wire. */ if (cn == NET_RX_DROP) { pr_debug("rx congestion\n"); break; } lapb->vr = (lapb->vr + 1) % modulus; lapb->condition &= ~LAPB_REJECT_CONDITION; if (frame->pf) lapb_enquiry_response(lapb); else { if (!(lapb->condition & LAPB_ACK_PENDING_CONDITION)) { lapb->condition |= LAPB_ACK_PENDING_CONDITION; lapb_start_t2timer(lapb); } } } else { if (lapb->condition & LAPB_REJECT_CONDITION) { if (frame->pf) lapb_enquiry_response(lapb); } else { lapb_dbg(1, "(%p) S3 TX REJ(%d) R%d\n", lapb->dev, frame->pf, lapb->vr); lapb->condition |= LAPB_REJECT_CONDITION; lapb_send_control(lapb, LAPB_REJ, frame->pf, LAPB_RESPONSE); lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; } } break; case LAPB_FRMR: lapb_dbg(1, "(%p) S3 RX FRMR(%d) %5ph\n", lapb->dev, frame->pf, skb->data); lapb_establish_data_link(lapb); lapb_dbg(0, "(%p) S3 -> S1\n", lapb->dev); lapb_requeue_frames(lapb); lapb->state = LAPB_STATE_1; break; case LAPB_ILLEGAL: lapb_dbg(1, "(%p) S3 RX ILLEGAL(%d)\n", lapb->dev, frame->pf); lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_W; lapb_transmit_frmr(lapb); lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; break; } if (!queued) kfree_skb(skb); }
static void lapb_t1timer_expiry(unsigned long param) { lapb_cb *lapb = (lapb_cb *)param; switch (lapb->state) { /* * If we are a DCE, keep going DM .. DM .. DM */ case LAPB_STATE_0: if (lapb->mode & LAPB_DCE) lapb_send_control(lapb, LAPB_DM, LAPB_POLLOFF, LAPB_RESPONSE); break; /* * Awaiting connection state, send SABM(E), up to N2 times. */ case LAPB_STATE_1: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token); #endif return; } else { lapb->n2count++; if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S1 TX SABME(1)\n", lapb->token); #endif lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S1 TX SABM(1)\n", lapb->token); #endif lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); } } break; /* * Awaiting disconnection state, send DISC, up to N2 times. */ case LAPB_STATE_2: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_disconnect_confirmation(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->token); #endif return; } else { lapb->n2count++; #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S2 TX DISC(1)\n", lapb->token); #endif lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND); } break; /* * Data transfer state, restransmit I frames, up to N2 times. */ case LAPB_STATE_3: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_stop_t2timer(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->token); #endif return; } else { lapb->n2count++; lapb_requeue_frames(lapb); } break; /* * Frame reject state, restransmit FRMR frames, up to N2 times. */ case LAPB_STATE_4: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->token); #endif return; } else { lapb->n2count++; lapb_transmit_frmr(lapb); } break; } lapb_start_t1timer(lapb); }
/* * State machine for state 3, Connected State. * The handling of the timer(s) is in file lapb_timer.c */ void lapb_state3_machine(struct lapb_cs * lapb, char * data, int data_size, struct lapb_frame * frame) { struct lapb_cs_internal * lapb_int = lapb_get_internal(lapb); //int queued = 0; int modulus = lapb_is_extended(lapb) ? LAPB_EMODULUS : LAPB_SMODULUS; switch (frame->type) { case LAPB_SABM: lapb->callbacks->debug(2, "[LAPB] S3 RX SABM(%d)", frame->pf); if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S3 TX DM(%d)", frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_OK); lapb_reset(lapb, LAPB_STATE_0); } else { lapb->callbacks->debug(2, "[LAPB] S3 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t201timer(lapb); lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; lapb_int->va = 0; lapb_requeue_frames(lapb); lapb_start_t201timer(lapb); /* to kick data */ }; break; case LAPB_SABME: lapb->callbacks->debug(2, "[LAPB] S3 RX SABME(%d)", frame->pf); if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S3 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t201timer(lapb); lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; lapb_int->va = 0; lapb_requeue_frames(lapb); lapb_start_t201timer(lapb); /* to kick data */ } else { lapb->callbacks->debug(2, "[LAPB] S3 TX DM(%d)", frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_OK); lapb_reset(lapb, LAPB_STATE_0); }; break; case LAPB_DISC: lapb->callbacks->debug(2, "[LAPB] S3 RX DISC(%d)", frame->pf); lapb->callbacks->debug(2, "[LAPB] S3 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_OK); lapb_reset(lapb, LAPB_STATE_0); break; case LAPB_DM: lapb->callbacks->debug(2, "[LAPB] S3 RX DM(%d)", frame->pf); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED); lapb_reset(lapb, LAPB_STATE_0); break; case LAPB_RNR: lapb->callbacks->debug(2, "[LAPB] S3 RX RNR(%d) R%d", frame->pf, frame->nr); lapb_int->condition |= LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb_int->frmr_data = *frame; lapb_int->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_int->condition = LAPB_FRMR_CONDITION; lapb_int->state = LAPB_STATE_4; lapb_int->RC = 0; lapb_start_t201timer(lapb); lapb_stop_t202timer(lapb); }; break; case LAPB_RR: lapb->callbacks->debug(2, "[LAPB] S3 RX RR(%d) R%d", frame->pf, frame->nr); lapb_int->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb_int->frmr_data = *frame; lapb_int->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_int->condition = LAPB_FRMR_CONDITION; lapb_int->state = LAPB_STATE_4; lapb_int->RC = 0; lapb_start_t201timer(lapb); lapb_stop_t202timer(lapb); }; break; case LAPB_REJ: lapb->callbacks->debug(2, "[LAPB] S3 RX REJ(%d) R%d", frame->pf, frame->nr); lapb_int->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_frames_acked(lapb, frame->nr); lapb_stop_t201timer(lapb); lapb_requeue_frames(lapb); } else { lapb_int->frmr_data = *frame; lapb_int->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_int->condition = LAPB_FRMR_CONDITION; lapb_int->state = LAPB_STATE_4; lapb_int->RC = 0; lapb_start_t201timer(lapb); lapb_stop_t202timer(lapb); }; break; case LAPB_I: if (lapb_int->condition & LAPB_FRMR_CONDITION) break; lapb->callbacks->debug(2, "[LAPB] S3 RX I(%d) S%d R%d", frame->pf, frame->ns, frame->nr); if (!lapb_validate_nr(lapb, frame->nr)) { lapb_int->frmr_data = *frame; lapb_int->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_int->condition = LAPB_FRMR_CONDITION; lapb_int->state = LAPB_STATE_4; lapb_int->RC = 0; lapb_start_t201timer(lapb); break; }; if (lapb_int->condition & LAPB_PEER_RX_BUSY_CONDITION) lapb_frames_acked(lapb, frame->nr); else lapb_check_iframes_acked(lapb, frame->nr); if (frame->ns == lapb_int->vr) { lapb_int->vr = (lapb_int->vr + 1) % modulus; lapb_int->condition |= LAPB_ACK_PENDING_CONDITION; int cn; if (lapb_is_extended(lapb)) cn = lapb_data_indication(lapb, data + 3, data_size - 3); else cn = lapb_data_indication(lapb, data + 2, data_size - 2); /* * If upper layer has dropped the frame, we * basically ignore any further protocol * processing. This will cause the peer * to re-transmit the frame later like * a frame lost on the wire. */ if (cn != 0) { lapb->callbacks->debug(1, "[LAPB] S3 Upper layer has dropped the frame"); break; }; //lapb_int->vr = (lapb_int->vr + 1) % modulus; lapb_int->condition &= ~LAPB_REJECT_CONDITION; if (lapb_int->condition & LAPB_ACK_PENDING_CONDITION) { /* Ack flag is still active */ if (frame->pf) lapb_enquiry_response(lapb); else { //if (!(lapb_int->condition & LAPB_ACK_PENDING_CONDITION)) { // lapb_int->condition |= LAPB_ACK_PENDING_CONDITION; lapb_start_t202timer(lapb); //}; //else // lapb->callbacks->debug(lapb, 1, "[LAPB] S3 lapb->condition=%d", lapb->condition); }; }; } else { if (lapb_int->condition & LAPB_REJECT_CONDITION) { if (frame->pf) lapb_enquiry_response(lapb); } else { lapb->callbacks->debug(2, "[LAPB] S3 TX REJ(%d) R%d", frame->pf, lapb_int->vr); lapb_int->condition |= LAPB_REJECT_CONDITION; lapb_send_control(lapb, LAPB_REJ, frame->pf, LAPB_RESPONSE); lapb_int->condition &= ~LAPB_ACK_PENDING_CONDITION; }; }; break; case LAPB_FRMR: lapb->callbacks->debug(2, "[LAPB] S3 RX FRMR(%d) %02X %02X %02X %02X %02X", frame->pf, (_uchar)data[0], (_uchar)data[1], (_uchar)data[2], (_uchar)data[3], (_uchar)data[4]); if (lapb_int->condition & LAPB_FRMR_CONDITION) { /* FRMR Collision */ lapb->callbacks->debug(2, "[LAPB] S3 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); break; }; lapb_int->condition = LAPB_FRMR_CONDITION; lapb_stop_t201timer(lapb); _ushort nr_tmp; if (lapb_is_extended(lapb)) nr_tmp = frame->control[1] >> 5; else nr_tmp = (_uchar)(data[3] >> 5) & 0x07; lapb_frames_acked(lapb, nr_tmp); lapb_requeue_frames(lapb); if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S3 TX SABME(1)"); lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { lapb->callbacks->debug(2, "[LAPB] S3 TX SABM(1)"); lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); }; break; case LAPB_UA: lapb->callbacks->debug(2, "[LAPB] S3 RX UA(%d)", frame->pf); if (lapb_int->condition & LAPB_FRMR_CONDITION) { lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; lapb_int->va = 0; lapb_start_t201timer(lapb); /* to kick data */ } else { /* Reset data link */ lapb_int->condition = LAPB_FRMR_CONDITION; lapb_requeue_frames(lapb); if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S3 TX SABME(1)"); lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { lapb->callbacks->debug(2, "[LAPB] S3 TX SABM(1)"); lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); }; }; break; case LAPB_ILLEGAL: lapb->callbacks->debug(2, "[LAPB] S3 RX ILLEGAL(%d)", frame->pf); lapb_int->frmr_data = *frame; lapb_int->frmr_type = LAPB_FRMR_W; lapb_transmit_frmr(lapb); lapb_int->condition = LAPB_FRMR_CONDITION; lapb_int->state = LAPB_STATE_4; lapb_start_t201timer(lapb); lapb_stop_t202timer(lapb); break; };
/* * State machine for state 1, Awaiting Connection State. * The handling of the timer(s) is in file lapb_timer.c. */ void lapb_state1_machine(struct lapb_cs * lapb, struct lapb_frame * frame) { struct lapb_cs_internal * lapb_int = lapb_get_internal(lapb); switch (frame->type) { case LAPB_SABM: lapb->callbacks->debug(2, "[LAPB] S1 RX SABM(%d)", frame->pf); if (lapb_is_extended(lapb)) { /* Unrecognized mode */ lapb->callbacks->debug(2, "[LAPB] S1 TX DM(%d)", frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } else { /* Collision state, send UA and switch to state_3 */ lapb->callbacks->debug(2, "[LAPB] S1 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t201timer(lapb); lapb_int->state = LAPB_STATE_3; lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; lapb_int->va = 0; lapb->callbacks->debug(1, "[LAPB] S1 -> S3"); lapb_connect_confirmation(lapb, LAPB_OK); }; break; case LAPB_SABME: lapb->callbacks->debug(2, "[LAPB] S1 RX SABME(%d)", frame->pf); if (lapb_is_extended(lapb)) { /* Collision state, send UA and switch to state_3 */ lapb->callbacks->debug(2, "[LAPB] S1 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t201timer(lapb); lapb_int->state = LAPB_STATE_3; lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; lapb_int->va = 0; lapb->callbacks->debug(1, "[LAPB] S1 -> S3"); lapb_connect_confirmation(lapb, LAPB_OK); } else { /* Unrecognized mode */ lapb->callbacks->debug(2, "[LAPB] S1 TX DM(%d)", frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); }; break; // case LAPB_DISC: // lapb->callbacks->debug(2, "[LAPB] S1 RX DISC(%d)", frame->pf); // lapb->callbacks->debug(2, "[LAPB] S1 TX DM(%d)", frame->pf); // lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); // lapb_requeue_frames(lapb); // lapb_disconnect_indication(lapb, LAPB_REFUSED); // lapb_reset(lapb, LAPB_STATE_0); // break; case LAPB_UA: lapb->callbacks->debug(2, "[LAPB] S1 RX UA(%d)", frame->pf); if (frame->pf) { lapb_stop_t201timer(lapb); lapb_int->state = LAPB_STATE_3; lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; lapb_int->va = 0; lapb->callbacks->debug(1, "[LAPB] S1 -> S3"); lapb_connect_confirmation(lapb, LAPB_OK); }; break; case LAPB_DM: lapb->callbacks->debug(2, "[LAPB] S1 RX DM(%d)", frame->pf); if (frame->pf) { lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_REFUSED); lapb_reset(lapb, LAPB_STATE_0); }; break; }; }
/* * State machine for state 0, Disconnected State. * The handling of the timer(s) is in file lapb_timer.c. */ static void lapb_state0_machine(struct lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame) { switch (frame->type) { case LAPB_SABM: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S0 RX SABM(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n", lapb->dev, frame->pf); #endif #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->dev); #endif lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_3; lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_connect_indication(lapb, LAPB_OK); } break; case LAPB_SABME: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S0 RX SABME(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n", lapb->dev, frame->pf); #endif #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->dev); #endif lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_3; lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_connect_indication(lapb, LAPB_OK); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } break; case LAPB_DISC: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S0 RX DISC(%d)\n", lapb->dev, frame->pf); printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); break; default: break; } kfree_skb(skb); }
/* * State machine for state 0, Disconnected State. * The handling of the timer(s) is in file lapb_timer.c. */ void lapb_state0_machine(struct lapb_cs * lapb, struct lapb_frame * frame) { struct lapb_cs_internal * lapb_int = lapb_get_internal(lapb); switch (frame->type) { case LAPB_SABM: lapb->callbacks->debug(2, "[LAPB] S0 RX SABM(%d)", frame->pf); if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S0 TX DM(%d)", frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } else { lapb_stop_t201timer(lapb); lapb->callbacks->debug(2, "[LAPB] S0 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_int->state = LAPB_STATE_3; lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; //lapb_int->last_vr = 0; lapb_int->va = 0; lapb->callbacks->debug(1, "[LAPB] S0 -> S3"); lapb_connect_indication(lapb, LAPB_OK); }; break; case LAPB_SABME: lapb->callbacks->debug(2, "[LAPB] S0 RX SABME(%d)", frame->pf); if (lapb_is_extended(lapb)) { lapb_stop_t201timer(lapb); lapb->callbacks->debug(2, "[LAPB] S0 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_int->state = LAPB_STATE_3; lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; //lapb_int->last_vr = 0; lapb_int->va = 0; lapb->callbacks->debug(1, "[LAPB] S0 -> S3"); lapb_connect_indication(lapb, LAPB_OK); } else { lapb->callbacks->debug(2, "[LAPB] S0 TX DM(%d)", frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); }; break; case LAPB_DM: if (!lapb->auto_connecting) break; lapb->callbacks->debug(2, "[LAPB] S0 RX DM(%d)", frame->pf); lapb_int->condition = 0x00; if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S0 TX SABME(1)"); lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { lapb->callbacks->debug(2, "[LAPB] S0 TX SABM(1)"); lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); }; lapb_int->state = LAPB_STATE_1; lapb->callbacks->debug(1, "[LAPB] S0 -> S1"); break; // case LAPB_DISC: // lapb_debug(lapb, 1, "[LAPB] S0 RX DISC(%d)", frame->pf); // lapb_debug(lapb, 1, "[LAPB] S0 TX UA(%d)", frame->pf); // lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); // break; default: break; }; }
static void lapb_t1timer_expiry(unsigned long param) { struct lapb_cb *lapb = (struct lapb_cb *)param; switch (lapb->state) { case LAPB_STATE_0: if (lapb->mode & LAPB_DCE) lapb_send_control(lapb, LAPB_DM, LAPB_POLLOFF, LAPB_RESPONSE); break; case LAPB_STATE_1: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev); #endif return; } else { lapb->n2count++; if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S1 TX SABME(1)\n", lapb->dev); #endif lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S1 TX SABM(1)\n", lapb->dev); #endif lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); } } break; case LAPB_STATE_2: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_disconnect_confirmation(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev); #endif return; } else { lapb->n2count++; #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S2 TX DISC(1)\n", lapb->dev); #endif lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND); } break; case LAPB_STATE_3: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_stop_t2timer(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev); #endif return; } else { lapb->n2count++; lapb_requeue_frames(lapb); } break; case LAPB_STATE_4: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->dev); #endif return; } else { lapb->n2count++; lapb_transmit_frmr(lapb); } break; } lapb_start_t1timer(lapb); }
static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame) { int queued = 0; int modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS; switch (frame->type) { case LAPB_SABM: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX SABM(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_requeue_frames(lapb); } break; case LAPB_SABME: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX SABME(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_requeue_frames(lapb); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } break; case LAPB_DISC: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX DISC(%d)\n", lapb->dev, frame->pf); #endif #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev); #endif lapb_clear_queues(lapb); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_0; lapb_disconnect_indication(lapb, LAPB_OK); break; case LAPB_DM: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX DM(%d)\n", lapb->dev, frame->pf); #endif #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev); #endif lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED); break; case LAPB_RNR: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX RNR(%d) R%d\n", lapb->dev, frame->pf, frame->nr); #endif lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev); #endif lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_RR: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX RR(%d) R%d\n", lapb->dev, frame->pf, frame->nr); #endif lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev); #endif lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_REJ: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n", lapb->dev, frame->pf, frame->nr); #endif lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_frames_acked(lapb, frame->nr); lapb_stop_t1timer(lapb); lapb->n2count = 0; lapb_requeue_frames(lapb); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev); #endif lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_I: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX I(%d) S%d R%d\n", lapb->dev, frame->pf, frame->ns, frame->nr); #endif if (!lapb_validate_nr(lapb, frame->nr)) { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev); #endif lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; break; } if (lapb->condition & LAPB_PEER_RX_BUSY_CONDITION) lapb_frames_acked(lapb, frame->nr); else lapb_check_iframes_acked(lapb, frame->nr); if (frame->ns == lapb->vr) { int cn; cn = lapb_data_indication(lapb, skb); queued = 1; /* */ if (cn == NET_RX_DROP) { printk(KERN_DEBUG "LAPB: rx congestion\n"); break; } lapb->vr = (lapb->vr + 1) % modulus; lapb->condition &= ~LAPB_REJECT_CONDITION; if (frame->pf) lapb_enquiry_response(lapb); else { if (!(lapb->condition & LAPB_ACK_PENDING_CONDITION)) { lapb->condition |= LAPB_ACK_PENDING_CONDITION; lapb_start_t2timer(lapb); } } } else { if (lapb->condition & LAPB_REJECT_CONDITION) { if (frame->pf) lapb_enquiry_response(lapb); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 TX REJ(%d) R%d\n", lapb->dev, frame->pf, lapb->vr); #endif lapb->condition |= LAPB_REJECT_CONDITION; lapb_send_control(lapb, LAPB_REJ, frame->pf, LAPB_RESPONSE); lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; } } break; case LAPB_FRMR: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX FRMR(%d) %02X " "%02X %02X %02X %02X\n", lapb->dev, frame->pf, skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4]); #endif lapb_establish_data_link(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->dev); #endif lapb_requeue_frames(lapb); lapb->state = LAPB_STATE_1; break; case LAPB_ILLEGAL: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX ILLEGAL(%d)\n", lapb->dev, frame->pf); #endif lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_W; lapb_transmit_frmr(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev); #endif lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; break; } if (!queued) kfree_skb(skb); }
void lapb_t201timer_expiry(void * lapb_ptr) { struct lapb_cs *lapb = lapb_ptr; if (!lapb) return; struct lapb_cs_internal * lapb_int = lapb_get_internal(lapb); lapb_int->RC++; lapb->callbacks->debug(3, "[LAPB] S%d Timer_201 expired(%d of %d)", lapb_int->state, lapb_int->RC, lapb->N201); switch (lapb_int->state) { /* * If we are a DCE, keep going DM .. DM .. DM */ case LAPB_STATE_0: if (lapb_is_dce(lapb)) { lapb_int->RC = 0; lapb->callbacks->debug(2, "[LAPB] S0 TX DM(0)"); lapb_send_control(lapb, LAPB_DM, LAPB_POLLOFF, LAPB_RESPONSE); }; break; /* * Awaiting connection state, send SABM(E), up to N2 times. */ case LAPB_STATE_1: if (lapb_int->RC >= lapb->N201) { lapb_stop_t201timer(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); lapb_reset(lapb, LAPB_STATE_0); } else { if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S1 TX SABME(1)"); lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { lapb->callbacks->debug(2, "[LAPB] S1 TX SABM(1)"); lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); }; }; break; /* * Awaiting disconnection state, send DISC, up to N2 times. */ case LAPB_STATE_2: if (lapb_int->RC >= lapb->N201) { lapb_stop_t201timer(lapb); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); lapb_reset(lapb, LAPB_STATE_0); } else { lapb->callbacks->debug(2, "[LAPB] S2 TX DISC(1)"); lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND); }; break; /* * Data transfer state, restransmit I frames, up to N2 times. */ case LAPB_STATE_3: lapb_requeue_frames(lapb); if (lapb_int->RC >= lapb->N201) { lapb_stop_t201timer(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); lapb_reset(lapb, LAPB_STATE_0); } else { if (lapb_int->condition & LAPB_FRMR_CONDITION) lapb_transmit_frmr(lapb); else lapb_kick(lapb); }; break; /* * Frame reject state, restransmit FRMR frames, up to N2 times. */ case LAPB_STATE_4: if (lapb_int->RC >= lapb->N201) { lapb_stop_t201timer(lapb); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); lapb_reset(lapb, LAPB_STATE_0); } else { lapb_transmit_frmr(lapb); }; break; }; }