From: Jasmin Jessich <jasmin.jessich@xxxxxxxxxxxxxx> Added ITU-T Q.921 mode to LAPB protocol driver (net/lapb/). Added dynamic switching of the debugging outputs using parameter setting. I have checked the Q.921 implementation against a Q.921 protocol tester. I couldn't check, if the x25 implementation is still working, because I have no protocol tester for x25 LAPB. I think I didn't touch the old functionality, but I would be happy if someone would test it. Signed-off-by: Jasmin Jessich <jasmin.jessich@xxxxxxxxxxxxxx> --- _________________________________________________________ Ing. Jasmin Jessich Software Engineer FREQUENTIS GmbH Innovationsstrasse 1, 1100 Vienna, Austria Phone +43-1-811 50 - 2395 Mobile - Fax +43-1-811 50 - 77 2395 Web www.frequentis.com E-Mail jasmin.jessich@xxxxxxxxxxxxxx Handelsgericht Wien (Vienna Commercial Court): FN 72115 b DVR 0364797, ATU 14715600 _________________________________________________________ Index: include/net/lapb.h =================================================================== --- include/net/lapb.h (revision 3155) +++ include/net/lapb.h (working copy) @@ -46,6 +46,12 @@ #define LAPB_ADDR_C 0x0F #define LAPB_ADDR_D 0x07 +/* LAPD ITU_T Q.921 mode command responses + * master: command = 1, response = 0 + * slave: command = 0, response = 1 + */ +#define LAPB_CMD_RESP 0x02 + /* Define Link State constants. */ enum { LAPB_STATE_0, /* Disconnected State */ @@ -60,10 +66,22 @@ #define LAPB_DEFAULT_T1 (5 * HZ) /* T1=5s */ #define LAPB_DEFAULT_T2 (1 * HZ) /* T2=1s */ #define LAPB_DEFAULT_N2 20 /* N2=20 */ +#define LAPB_DEFAULT_SAPI 0 +#define LAPB_DEFAULT_TEI 0 +#define LAPB_DEFAULT_T203 (10 * HZ) /* T203=10s */ #define LAPB_SMODULUS 8 #define LAPB_EMODULUS 128 +#define LAPB_Q921_FLG_ESTABLISH_ALLOWED 0x01 +#define LAPB_Q921_FLG_DO_DISCONNECT 0x02 +#define LAPB_Q921_FLG_L3_INITIATED 0x04 +#define LAPB_Q921_FLG_TIMER_RECOVERY 0x08 +#define LAPB_Q921_FLG_T203 0x10 + +/* Dynamical debugging en/disabled (1/0) */ +#define LAPB_DEBUG_DYN 0 + /* * Information about the current frame. */ @@ -88,7 +106,9 @@ unsigned short vs, vr, va; unsigned char condition; unsigned short n2, n2count; - unsigned short t1, t2; + unsigned short t1, t2, t203; + unsigned char sapi, tei; + unsigned char q921_flags; struct timer_list t1timer, t2timer; /* Internal control information */ @@ -97,6 +117,10 @@ unsigned char window; struct lapb_register_struct callbacks; +#if LAPB_DEBUG_DYN == 1 + unsigned int dbg_level; +#endif + /* FRMR control information */ struct lapb_frame frmr_data; unsigned char frmr_type; @@ -119,10 +143,12 @@ extern void lapb_kick(struct lapb_cb *lapb); extern void lapb_transmit_buffer(struct lapb_cb *lapb, struct sk_buff *, int); extern void lapb_establish_data_link(struct lapb_cb *lapb); -extern void lapb_enquiry_response(struct lapb_cb *lapb); +extern void lapb_reestablish(struct lapb_cb *lapb); +extern void lapb_enquiry_response(struct lapb_cb *lapb, int); extern void lapb_timeout_response(struct lapb_cb *lapb); extern void lapb_check_iframes_acked(struct lapb_cb *lapb, unsigned short); extern void lapb_check_need_response(struct lapb_cb *lapb, int, int); +extern void lapb_initialize_retransmission(struct lapb_cb *lapb); /* lapb_subr.c */ extern void lapb_clear_queues(struct lapb_cb *lapb); @@ -136,6 +162,7 @@ /* lapb_timer.c */ extern void lapb_start_t1timer(struct lapb_cb *lapb); extern void lapb_start_t2timer(struct lapb_cb *lapb); +extern void lapb_start_t203(struct lapb_cb *lapb); extern void lapb_stop_t1timer(struct lapb_cb *lapb); extern void lapb_stop_t2timer(struct lapb_cb *lapb); extern int lapb_t1timer_running(struct lapb_cb *lapb); @@ -149,4 +176,19 @@ */ #define LAPB_DEBUG 0 +#if LAPB_DEBUG_DYN == 1 + +/* Dynamical debugging needs all debug printouts enabled */ +# undef LAPB_DEBUG +# define LAPB_DEBUG 3 + +# define LAPB_DEBUG_DYN_LEVEL_DEFAULT 2 + +# define LAPB_DEBUG_DYN_CHK( _p_lapb, _level ) \ + if (_p_lapb->dbg_level > _level ) +#else +# define LAPB_DEBUG_DYN_CHK( _p_lapb, _level ) + #endif + +#endif Index: include/linux/lapb.h =================================================================== --- include/linux/lapb.h (revision 3155) +++ include/linux/lapb.h (working copy) @@ -23,6 +23,12 @@ #define LAPB_DTE 0x00 #define LAPB_DCE 0x04 +/* LAPD according to ITU-T Q.921 specification + * slave side configured with LAPB_SLP + * master side configured with LAPB_MLP + */ +#define LAPB_Q921 0x08 + struct lapb_register_struct { void (*connect_confirmation)(struct net_device *dev, int reason); void (*connect_indication)(struct net_device *dev, int reason); @@ -42,6 +48,11 @@ unsigned int window; unsigned int state; unsigned int mode; + unsigned int sapi; + unsigned int tei; + unsigned int t203; + unsigned int t203timer; + unsigned int dbg_level; }; extern int lapb_register(struct net_device *dev, struct lapb_register_struct *callbacks); Index: net/lapb/lapb_timer.c =================================================================== --- net/lapb/lapb_timer.c (revision 3155) +++ net/lapb/lapb_timer.c (working copy) @@ -54,11 +54,20 @@ lapb->t2timer.data = (unsigned long)lapb; lapb->t2timer.function = &lapb_t2timer_expiry; - lapb->t2timer.expires = jiffies + lapb->t2; + lapb->t2timer.expires = jiffies + + (lapb->q921_flags & LAPB_Q921_FLG_T203 ? lapb->t203 : lapb->t2); add_timer(&lapb->t2timer); } +void lapb_start_t203(struct lapb_cb *lapb) +{ + if (lapb->mode & LAPB_Q921) { + lapb->q921_flags |= LAPB_Q921_FLG_T203; + lapb_start_t2timer(lapb); + } +} + void lapb_stop_t1timer(struct lapb_cb *lapb) { del_timer(&lapb->t1timer); @@ -67,6 +76,7 @@ void lapb_stop_t2timer(struct lapb_cb *lapb) { del_timer(&lapb->t2timer); + lapb->q921_flags &= ~LAPB_Q921_FLG_T203; } int lapb_t1timer_running(struct lapb_cb *lapb) @@ -78,7 +88,15 @@ { struct lapb_cb *lapb = (struct lapb_cb *)param; - if (lapb->condition & LAPB_ACK_PENDING_CONDITION) { + if (lapb->mode & LAPB_Q921 && + lapb->q921_flags & LAPB_Q921_FLG_T203) { + lapb->q921_flags &= ~LAPB_Q921_FLG_T203; + if (lapb->state == LAPB_STATE_3) { + lapb->q921_flags |= LAPB_Q921_FLG_TIMER_RECOVERY; + lapb_enquiry_response(lapb, LAPB_COMMAND); + lapb_start_t1timer(lapb); + } + } else if (lapb->condition & LAPB_ACK_PENDING_CONDITION) { lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; lapb_timeout_response(lapb); } @@ -94,9 +112,14 @@ * If we are a DCE, keep going DM .. DM .. DM */ case LAPB_STATE_0: + if (!(lapb->mode & LAPB_Q921)) { if (lapb->mode & LAPB_DCE) lapb_send_control(lapb, LAPB_DM, LAPB_POLLOFF, LAPB_RESPONSE); - break; + } else { + /* do not restart timer */ + return; + } + break; /* * Awaiting connection state, send SABM(E), up to N2 times. @@ -104,9 +127,11 @@ case LAPB_STATE_1: if (lapb->n2count == lapb->n2) { lapb_clear_queues(lapb); + lapb->q921_flags &= ~LAPB_Q921_FLG_DO_DISCONNECT; lapb->state = LAPB_STATE_0; lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev); #endif return; @@ -114,11 +139,13 @@ lapb->n2count++; if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 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 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 TX SABM(1)\n", lapb->dev); #endif lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); @@ -135,12 +162,14 @@ lapb->state = LAPB_STATE_0; lapb_disconnect_confirmation(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev); #endif return; } else { lapb->n2count++; #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S2 TX DISC(1)\n", lapb->dev); #endif lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND); @@ -152,17 +181,35 @@ */ case LAPB_STATE_3: if (lapb->n2count == lapb->n2) { + if (lapb->mode & LAPB_Q921) { + lapb_reestablish(lapb); + return; + } lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_stop_t2timer(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev); #endif return; } else { lapb->n2count++; - lapb_requeue_frames(lapb); + if (lapb->mode & LAPB_Q921) { + lapb->q921_flags |= + LAPB_Q921_FLG_TIMER_RECOVERY; + /* lapb_requeue_frames would requeue + * all frames, but Q.921 needs to send + * only the last transmitted I frame. + * There is an implementation option to + * send an enquery. Not requeuing and + * immediately sending the the RR will + * choose this option. + */ + lapb_enquiry_response(lapb, LAPB_COMMAND); + } else + lapb_requeue_frames(lapb); } break; @@ -175,6 +222,7 @@ lapb->state = LAPB_STATE_0; lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->dev); #endif return; Index: net/lapb/lapb_in.c =================================================================== --- net/lapb/lapb_in.c (revision 3155) +++ net/lapb/lapb_in.c (working copy) @@ -46,11 +46,13 @@ switch (frame->type) { case LAPB_SABM: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 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 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n", lapb->dev, frame->pf); #endif @@ -58,10 +60,12 @@ LAPB_RESPONSE); } else { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n", lapb->dev, frame->pf); #endif #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->dev); #endif @@ -72,6 +76,8 @@ lapb->state = LAPB_STATE_3; lapb->condition = 0x00; lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; @@ -81,15 +87,32 @@ case LAPB_SABME: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S0 RX SABME(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { + if (lapb->mode & LAPB_Q921 && + !(lapb->q921_flags & + LAPB_Q921_FLG_ESTABLISH_ALLOWED)) { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 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; + } +#if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n", lapb->dev, frame->pf); #endif #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->dev); #endif @@ -100,12 +123,16 @@ lapb->state = LAPB_STATE_3; lapb->condition = 0x00; lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; + lapb_start_t203(lapb); lapb_connect_indication(lapb, LAPB_OK); } else { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n", lapb->dev, frame->pf); #endif @@ -116,8 +143,22 @@ case LAPB_DISC: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S0 RX DISC(%d)\n", lapb->dev, frame->pf); +#endif + if (lapb->mode & LAPB_Q921) { +#if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 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; + } +#if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n", lapb->dev, frame->pf); #endif @@ -125,6 +166,31 @@ LAPB_RESPONSE); break; + case LAPB_DM: + if (lapb->mode & LAPB_Q921) { +#if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) + printk(KERN_DEBUG "lapb: (%p) S0 RX DM(%d)\n", + lapb->dev, frame->pf); +#endif + if (!frame->pf && + lapb->q921_flags & + LAPB_Q921_FLG_ESTABLISH_ALLOWED) { + lapb_establish_data_link(lapb); + lapb->q921_flags |= + LAPB_Q921_FLG_L3_INITIATED; + +#if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) + printk(KERN_DEBUG + "lapb: (%p) S0 -> S1\n", + lapb->dev); +#endif + lapb->state = LAPB_STATE_1; + } + } + break; + default: break; } @@ -142,11 +208,13 @@ switch (frame->type) { case LAPB_SABM: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 RX SABM(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n", lapb->dev, frame->pf); #endif @@ -154,6 +222,7 @@ LAPB_RESPONSE); } else { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n", lapb->dev, frame->pf); #endif @@ -164,11 +233,13 @@ case LAPB_SABME: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 RX SABME(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n", lapb->dev, frame->pf); #endif @@ -176,6 +247,7 @@ LAPB_RESPONSE); } else { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n", lapb->dev, frame->pf); #endif @@ -186,8 +258,10 @@ case LAPB_DISC: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 RX DISC(%d)\n", lapb->dev, frame->pf); + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n", lapb->dev, frame->pf); #endif @@ -197,11 +271,71 @@ case LAPB_UA: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 RX UA(%d)\n", lapb->dev, frame->pf); #endif if (frame->pf) { + if (lapb->mode & LAPB_Q921) { + if (lapb-> q921_flags & + LAPB_Q921_FLG_L3_INITIATED) { + lapb->q921_flags &= + ~LAPB_Q921_FLG_L3_INITIATED; + lapb->vr = 0; + } else if (lapb->vs != lapb->va) { + lapb_clear_queues(lapb); + } + lapb_connect_confirmation(lapb, + LAPB_OK); + if (lapb->q921_flags & + LAPB_Q921_FLG_DO_DISCONNECT) { + lapb->q921_flags &= + ~LAPB_Q921_FLG_DO_DISCONNECT; + lapb->condition = 0x00; + lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; + lapb->vs = 0; + lapb->va = 0; + lapb_clear_queues(lapb); + 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 + LAPB_DEBUG_DYN_CHK(lapb, 1) + printk(KERN_DEBUG + "lapb: (%p) S1 TX DISC(1)\n", + lapb->dev); +#endif #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) + printk(KERN_DEBUG + "lapb: (%p) S1 -> S2\n", + lapb->dev); +#endif + } else { +#if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) + printk(KERN_DEBUG + "lapb: (%p) S1 -> S3\n", + lapb->dev); +#endif + lapb_stop_t1timer(lapb); + lapb_start_t203(lapb); + lapb->state = LAPB_STATE_3; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; + lapb->vs = 0; + lapb->va = 0; + } + break; + } +#if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S1 -> S3\n", lapb->dev); #endif @@ -219,15 +353,19 @@ case LAPB_DM: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 RX DM(%d)\n", lapb->dev, frame->pf); #endif if (frame->pf) { #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev); #endif lapb_clear_queues(lapb); + lapb->q921_flags &= + ~LAPB_Q921_FLG_DO_DISCONNECT; lapb->state = LAPB_STATE_0; lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); @@ -250,8 +388,10 @@ case LAPB_SABM: case LAPB_SABME: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S2 RX {SABM,SABME}(%d)\n", lapb->dev, frame->pf); + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S2 TX DM(%d)\n", lapb->dev, frame->pf); #endif @@ -261,8 +401,10 @@ case LAPB_DISC: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S2 RX DISC(%d)\n", lapb->dev, frame->pf); + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S2 TX UA(%d)\n", lapb->dev, frame->pf); #endif @@ -272,11 +414,13 @@ case LAPB_UA: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S2 RX UA(%d)\n", lapb->dev, frame->pf); #endif if (frame->pf) { #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev); #endif @@ -289,11 +433,13 @@ case LAPB_DM: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n", lapb->dev, frame->pf); #endif if (frame->pf) { #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev); #endif @@ -309,15 +455,23 @@ case LAPB_REJ: case LAPB_RNR: case LAPB_RR: + if (lapb->mode & LAPB_Q921) { + break; + } #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S2 RX {I,REJ,RNR,RR}" "(%d)\n", lapb->dev, frame->pf); - printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n", - lapb->dev, frame->pf); #endif - if (frame->pf) + if (frame->pf) { +#if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) + printk(KERN_DEBUG "lapb: (%p) S2 TX DM(%d)\n", + lapb->dev, frame->pf); +#endif lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); + } break; } @@ -334,15 +488,18 @@ int queued = 0; int modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS; + int checknr = 1; switch (frame->type) { case LAPB_SABM: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 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 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n", lapb->dev, frame->pf); #endif @@ -350,6 +507,7 @@ LAPB_RESPONSE); } else { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n", lapb->dev, frame->pf); #endif @@ -359,6 +517,8 @@ lapb_stop_t2timer(lapb); lapb->condition = 0x00; lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; @@ -368,11 +528,13 @@ case LAPB_SABME: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 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 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n", lapb->dev, frame->pf); #endif @@ -382,12 +544,23 @@ lapb_stop_t2timer(lapb); lapb->condition = 0x00; lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; + if (lapb->mode & LAPB_Q921) { + if (lapb->vs != lapb->va) { + lapb_clear_queues(lapb); + lapb_connect_confirmation + (lapb, LAPB_OK); + } + } lapb->vs = 0; lapb->vr = 0; lapb->va = 0; + lapb_start_t203(lapb); lapb_requeue_frames(lapb); } else { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n", lapb->dev, frame->pf); #endif @@ -398,10 +571,17 @@ case LAPB_DISC: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S3 RX DISC(%d)\n", lapb->dev, frame->pf); #endif +#if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) + printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n", + lapb->dev, frame->pf); +#endif #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev); #endif @@ -411,15 +591,36 @@ lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_0; + lapb->q921_flags &= ~LAPB_Q921_FLG_TIMER_RECOVERY; lapb_disconnect_indication(lapb, LAPB_OK); break; + case LAPB_UA: + if (lapb->mode & LAPB_Q921) { +#if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) + printk(KERN_DEBUG "lapb: (%p) S3 RX UA(%d)\n", + lapb->dev, frame->pf); +#endif + } + break; + case LAPB_DM: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S3 RX DM(%d)\n", lapb->dev, frame->pf); #endif + if (lapb->mode & LAPB_Q921) { + if (!frame->pf || + lapb->q921_flags & + LAPB_Q921_FLG_TIMER_RECOVERY) { + lapb_reestablish(lapb); + } + break; + } #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev); #endif @@ -432,54 +633,105 @@ case LAPB_RNR: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 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); + if (!(lapb->q921_flags & + LAPB_Q921_FLG_TIMER_RECOVERY)) { + if (!lapb->mode & LAPB_Q921) { + lapb_check_iframes_acked + (lapb, frame->nr); + } else { + lapb_frames_acked(lapb, + frame->nr); + lapb_stop_t2timer(lapb); + lapb_start_t1timer(lapb); + } + } else { + lapb_frames_acked(lapb, frame->nr); + if (frame->cr == LAPB_RESPONSE && + frame->pf) { + lapb_start_t1timer(lapb); + lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; + lapb_requeue_frames(lapb); + } + } } else { - lapb->frmr_data = *frame; - lapb->frmr_type = LAPB_FRMR_Z; - lapb_transmit_frmr(lapb); + if (lapb->mode & LAPB_Q921) { + lapb_reestablish(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); + LAPB_DEBUG_DYN_CHK(lapb, 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; + lapb_start_t1timer(lapb); + lapb_stop_t2timer(lapb); + lapb->state = LAPB_STATE_4; + lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; + } } break; case LAPB_RR: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 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); + if (!(lapb->q921_flags & + LAPB_Q921_FLG_TIMER_RECOVERY)) { + lapb_check_iframes_acked(lapb, + frame->nr); + } else { + lapb_frames_acked(lapb, frame->nr); + if (frame->cr == LAPB_RESPONSE && + frame->pf) { + lapb_initialize_retransmission + (lapb); + } + } } else { - lapb->frmr_data = *frame; - lapb->frmr_type = LAPB_FRMR_Z; - lapb_transmit_frmr(lapb); + if (lapb->mode & LAPB_Q921) { + lapb_reestablish(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); + LAPB_DEBUG_DYN_CHK(lapb, 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; + lapb_start_t1timer(lapb); + lapb_stop_t2timer(lapb); + lapb->state = LAPB_STATE_4; + lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; + } } break; case LAPB_REJ: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n", lapb->dev, frame->pf, frame->nr); #endif @@ -487,47 +739,78 @@ 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); + if (!(lapb->q921_flags & + LAPB_Q921_FLG_TIMER_RECOVERY)) { + lapb_initialize_retransmission(lapb); + } else { + if (frame->cr == LAPB_RESPONSE && + frame->pf) { + lapb_initialize_retransmission + (lapb); + } + } } else { - lapb->frmr_data = *frame; - lapb->frmr_type = LAPB_FRMR_Z; - lapb_transmit_frmr(lapb); + if (lapb->mode & LAPB_Q921) { + lapb_reestablish(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); + LAPB_DEBUG_DYN_CHK(lapb, 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; + lapb_start_t1timer(lapb); + lapb_stop_t2timer(lapb); + lapb->state = LAPB_STATE_4; + lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; + } } break; case LAPB_I: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 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->mode & LAPB_Q921) { + lapb_reestablish(lapb); + checknr = 0; + } 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); + LAPB_DEBUG_DYN_CHK(lapb, 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; + lapb_start_t1timer(lapb); + lapb_stop_t2timer(lapb); + lapb->state = LAPB_STATE_4; + lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; + break; + } } - if (lapb->condition & LAPB_PEER_RX_BUSY_CONDITION) - lapb_frames_acked(lapb, frame->nr); - else - lapb_check_iframes_acked(lapb, frame->nr); + if (checknr) { + if ((lapb->condition & + LAPB_PEER_RX_BUSY_CONDITION) || + (lapb->q921_flags & + LAPB_Q921_FLG_TIMER_RECOVERY)) + lapb_frames_acked(lapb, frame->nr); + else + lapb_check_iframes_acked(lapb, + frame->nr); + } if (frame->ns == lapb->vr) { int cn; @@ -548,20 +831,25 @@ lapb->vr = (lapb->vr + 1) % modulus; lapb->condition &= ~LAPB_REJECT_CONDITION; if (frame->pf) - lapb_enquiry_response(lapb); + lapb_enquiry_response(lapb, + LAPB_RESPONSE); else { if (!(lapb->condition & LAPB_ACK_PENDING_CONDITION)) { lapb->condition |= LAPB_ACK_PENDING_CONDITION; - lapb_start_t2timer(lapb); + if (!lapb->mode & LAPB_Q921) { + lapb_start_t2timer(lapb); + } } } } else { if (lapb->condition & LAPB_REJECT_CONDITION) { if (frame->pf) - lapb_enquiry_response(lapb); + lapb_enquiry_response + (lapb, LAPB_RESPONSE); } else { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S3 TX REJ(%d) R%d\n", lapb->dev, frame->pf, lapb->vr); @@ -577,6 +865,7 @@ case LAPB_FRMR: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 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], @@ -584,28 +873,41 @@ #endif lapb_establish_data_link(lapb); #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->dev); #endif - lapb_requeue_frames(lapb); + if (lapb->mode & LAPB_Q921) { + lapb->q921_flags &= ~LAPB_Q921_FLG_L3_INITIATED; + } else { + lapb_requeue_frames(lapb); + } lapb->state = LAPB_STATE_1; break; case LAPB_ILLEGAL: + if (lapb->mode & LAPB_Q921) { + lapb_reestablish(lapb); + } else { #if LAPB_DEBUG > 1 - printk(KERN_DEBUG "lapb: (%p) S3 RX ILLEGAL(%d)\n", - lapb->dev, frame->pf); + LAPB_DEBUG_DYN_CHK(lapb, 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); + 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); + LAPB_DEBUG_DYN_CHK(lapb, 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; + lapb_start_t1timer(lapb); + lapb_stop_t2timer(lapb); + lapb->state = LAPB_STATE_4; + lapb->n2count = 0; + lapb->q921_flags &= ~LAPB_Q921_FLG_TIMER_RECOVERY; + } break; } @@ -623,11 +925,13 @@ switch (frame->type) { case LAPB_SABM: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S4 RX SABM(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n", lapb->dev, frame->pf); #endif @@ -635,10 +939,12 @@ LAPB_RESPONSE); } else { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n", lapb->dev, frame->pf); #endif #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->dev); #endif @@ -658,15 +964,18 @@ case LAPB_SABME: #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S4 RX SABME(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n", lapb->dev, frame->pf); #endif #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->dev); #endif @@ -677,12 +986,15 @@ lapb->state = LAPB_STATE_3; lapb->condition = 0x00; lapb->n2count = 0; + lapb->q921_flags &= + ~LAPB_Q921_FLG_TIMER_RECOVERY; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_connect_indication(lapb, LAPB_OK); } else { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n", lapb->dev, frame->pf); #endif Index: net/lapb/lapb_iface.c =================================================================== --- net/lapb/lapb_iface.c (revision 3155) +++ net/lapb/lapb_iface.c (working copy) @@ -132,7 +132,14 @@ lapb->n2 = LAPB_DEFAULT_N2; lapb->mode = LAPB_DEFAULT_MODE; lapb->window = LAPB_DEFAULT_WINDOW; + lapb->sapi = LAPB_DEFAULT_SAPI; + lapb->tei = LAPB_DEFAULT_TEI; lapb->state = LAPB_STATE_0; + lapb->t203 = LAPB_DEFAULT_T203; + lapb->q921_flags = 0x00; +#if LAPB_DEBUG_DYN == 1 + lapb->dbg_level = LAPB_DEBUG_DYN_LEVEL_DEFAULT; +#endif atomic_set(&lapb->refcnt, 1); out: return lapb; @@ -208,16 +215,28 @@ parms->state = lapb->state; parms->window = lapb->window; parms->mode = lapb->mode; + parms->sapi = lapb->sapi; + parms->tei = lapb->tei; + parms->t203 = lapb->t203 / HZ; +#if LAPB_DEBUG_DYN == 1 + parms->dbg_level = lapb->dbg_level; +#endif if (!timer_pending(&lapb->t1timer)) parms->t1timer = 0; else parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ; - if (!timer_pending(&lapb->t2timer)) + if (!timer_pending(&lapb->t2timer)) { parms->t2timer = 0; - else + parms->t203timer = 0; + } else { parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ; + if (lapb->q921_flags & LAPB_Q921_FLG_T203) { + parms->t203timer = parms->t2timer; + parms->t2timer = 0; + } + } lapb_put(lapb); rc = LAPB_OK; @@ -233,8 +252,16 @@ if (!lapb) goto out; +#if LAPB_DEBUG_DYN == 1 + if (lapb->dbg_level != parms->dbg_level) { + lapb->dbg_level = parms->dbg_level; + rc = LAPB_OK; + goto out_put; + } +#endif + rc = LAPB_INVALUE; - if (parms->t1 < 1 || parms->t2 < 1 || parms->n2 < 1) + if (parms->t1 < 1 || parms->t2 < 1 || parms->n2 < 1 || parms->t203 < 1) goto out_put; if (lapb->state == LAPB_STATE_0) { @@ -247,10 +274,18 @@ } lapb->mode = parms->mode; lapb->window = parms->window; + lapb->sapi = parms->sapi; + lapb->tei = parms->tei; + if (lapb->mode & LAPB_Q921) { + lapb->mode |= LAPB_EXTENDED; + } else if (!lapb_t1timer_running(lapb)) { + lapb_start_t1timer(lapb); + } } lapb->t1 = parms->t1 * HZ; lapb->t2 = parms->t2 * HZ; + lapb->t203 = parms->t203 * HZ; lapb->n2 = parms->n2; rc = LAPB_OK; @@ -268,17 +303,31 @@ if (!lapb) goto out; + lapb->q921_flags |= LAPB_Q921_FLG_ESTABLISH_ALLOWED | + LAPB_Q921_FLG_L3_INITIATED; + lapb->q921_flags &= ~LAPB_Q921_FLG_DO_DISCONNECT; + rc = LAPB_OK; - if (lapb->state == LAPB_STATE_1) + if (lapb->state == LAPB_STATE_1) { + if (lapb->mode & LAPB_Q921) { + lapb_clear_queues(lapb); + } goto out_put; + } rc = LAPB_CONNECTED; if (lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4) goto out_put; + if (lapb->mode & LAPB_Q921 && + lapb->q921_flags & LAPB_Q921_FLG_TIMER_RECOVERY) { + lapb_clear_queues(lapb); + } + lapb_establish_data_link(lapb); #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S0 -> S1\n", lapb->dev); #endif lapb->state = LAPB_STATE_1; @@ -298,16 +347,25 @@ if (!lapb) goto out; + lapb->q921_flags &= ~LAPB_Q921_FLG_ESTABLISH_ALLOWED; + switch (lapb->state) { case LAPB_STATE_0: rc = LAPB_NOTCONNECTED; goto out_put; case LAPB_STATE_1: + if (lapb->mode & LAPB_Q921) { + lapb->q921_flags |= LAPB_Q921_FLG_DO_DISCONNECT; + rc = LAPB_NOTCONNECTED; + goto out_put; + } #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->dev); #endif #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev); #endif lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND); @@ -323,15 +381,18 @@ lapb_clear_queues(lapb); lapb->n2count = 0; + lapb->q921_flags &= ~LAPB_Q921_FLG_TIMER_RECOVERY; 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->dev); + LAPB_DEBUG_DYN_CHK(lapb, 1) + printk(KERN_DEBUG "lapb: (%p) S3 TX DISC(1)\n", lapb->dev); #endif #if LAPB_DEBUG > 0 + LAPB_DEBUG_DYN_CHK(lapb, 0) printk(KERN_DEBUG "lapb: (%p) S3 -> S2\n", lapb->dev); #endif @@ -351,8 +412,16 @@ goto out; rc = LAPB_NOTCONNECTED; - if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4) + if (lapb->mode & LAPB_Q921 && lapb->state == LAPB_STATE_1) { + if (!(lapb->q921_flags & LAPB_Q921_FLG_L3_INITIATED)) { + skb_queue_tail(&lapb->write_queue, skb); + rc = LAPB_OK; + } goto out_put; + } else { + if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4) + goto out_put; + } skb_queue_tail(&lapb->write_queue, skb); lapb_kick(lapb); Index: net/lapb/lapb_out.c =================================================================== --- net/lapb/lapb_out.c (revision 3155) +++ net/lapb/lapb_out.c (working copy) @@ -62,6 +62,7 @@ } #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S%d TX I(%d) S%d R%d\n", lapb->dev, lapb->state, poll_bit, lapb->vs, lapb->vr); #endif @@ -79,6 +80,7 @@ end = (lapb->va + lapb->window) % modulus; if (!(lapb->condition & LAPB_PEER_RX_BUSY_CONDITION) && + !(lapb->q921_flags & LAPB_Q921_FLG_TIMER_RECOVERY) && start != end && skb_peek(&lapb->write_queue)) { lapb->vs = start; @@ -112,8 +114,15 @@ lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; - if (!lapb_t1timer_running(lapb)) + if (!lapb_t1timer_running(lapb)) { lapb_start_t1timer(lapb); + if (lapb->mode & LAPB_Q921) { + lapb_stop_t2timer(lapb); + } + } + } else if (lapb->mode & LAPB_Q921 && + lapb->condition & LAPB_ACK_PENDING_CONDITION) { + lapb_timeout_response(lapb); } } @@ -121,38 +130,67 @@ { unsigned char *ptr; - ptr = skb_push(skb, 1); + if (lapb->mode & LAPB_Q921) { + ptr = skb_push(skb, 2); - if (lapb->mode & LAPB_MLP) { - if (lapb->mode & LAPB_DCE) { + ptr[0] = lapb->sapi << 2; + ptr[1] = lapb->tei << 1 | 0x01; + + if (lapb->mode & LAPB_MLP) { if (type == LAPB_COMMAND) - *ptr = LAPB_ADDR_C; - if (type == LAPB_RESPONSE) - *ptr = LAPB_ADDR_D; + ptr[0] |= LAPB_CMD_RESP; } else { - if (type == LAPB_COMMAND) - *ptr = LAPB_ADDR_D; if (type == LAPB_RESPONSE) - *ptr = LAPB_ADDR_C; + ptr[0] |= LAPB_CMD_RESP; } } else { - if (lapb->mode & LAPB_DCE) { - if (type == LAPB_COMMAND) - *ptr = LAPB_ADDR_A; - if (type == LAPB_RESPONSE) - *ptr = LAPB_ADDR_B; + ptr = skb_push(skb, 1); + + if (lapb->mode & LAPB_MLP) { + if (lapb->mode & LAPB_DCE) { + if (type == LAPB_COMMAND) + *ptr = LAPB_ADDR_C; + if (type == LAPB_RESPONSE) + *ptr = LAPB_ADDR_D; + } else { + if (type == LAPB_COMMAND) + *ptr = LAPB_ADDR_D; + if (type == LAPB_RESPONSE) + *ptr = LAPB_ADDR_C; + } } else { - if (type == LAPB_COMMAND) - *ptr = LAPB_ADDR_B; - if (type == LAPB_RESPONSE) - *ptr = LAPB_ADDR_A; + if (lapb->mode & LAPB_DCE) { + if (type == LAPB_COMMAND) + *ptr = LAPB_ADDR_A; + if (type == LAPB_RESPONSE) + *ptr = LAPB_ADDR_B; + } else { + if (type == LAPB_COMMAND) + *ptr = LAPB_ADDR_B; + if (type == LAPB_RESPONSE) + *ptr = LAPB_ADDR_A; + } } } #if LAPB_DEBUG > 2 - printk(KERN_DEBUG "lapb: (%p) S%d TX %02X %02X %02X\n", - lapb->dev, lapb->state, - skb->data[0], skb->data[1], skb->data[2]); + if (lapb->mode & LAPB_Q921) { + /* struct timeval tim; + * jiffies_to_timeval(jiffies, &tim); + */ + LAPB_DEBUG_DYN_CHK(lapb, 2) + printk(KERN_DEBUG + /* "lapb: (%p) S%d Tim:%lu.%3.3lu TX %02X %02X %02X %02X\n", */ + "lapb: (%p) S%d TX %02X %02X %02X %02X\n", + lapb->dev, lapb->state, /* tim.tv_sec, tim.tv_usec / 1000, */ + skb->data[0], skb->data[1], + skb->data[2], skb->data[3]); + } else { + LAPB_DEBUG_DYN_CHK(lapb, 2) + printk(KERN_DEBUG "lapb: (%p) S%d TX %02X %02X %02X\n", + lapb->dev, lapb->state, + skb->data[0], skb->data[1], skb->data[2]); + } #endif if (!lapb_data_transmit(lapb, skb)) @@ -163,15 +201,18 @@ { lapb->condition = 0x00; lapb->n2count = 0; + lapb->q921_flags &= ~LAPB_Q921_FLG_TIMER_RECOVERY; if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S%d TX SABME(1)\n", lapb->dev, lapb->state); #endif lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S%d TX SABM(1)\n", lapb->dev, lapb->state); #endif @@ -182,14 +223,35 @@ lapb_stop_t2timer(lapb); } -void lapb_enquiry_response(struct lapb_cb *lapb) +void lapb_reestablish(struct lapb_cb *lapb) { + lapb_establish_data_link(lapb); + + lapb->q921_flags &= ~LAPB_Q921_FLG_L3_INITIATED; + +#if LAPB_DEBUG > 0 + { + static const char *txtState[] = + { "S0", "S1", "S2", "S3", "S4" }; + LAPB_DEBUG_DYN_CHK(lapb, 0) + printk(KERN_DEBUG "lapb: (%p) %s -> S1\n", lapb->dev, + txtState[lapb->state] ); + } +#endif + + lapb->q921_flags &= ~LAPB_Q921_FLG_TIMER_RECOVERY; + lapb->state = LAPB_STATE_1; +} + +void lapb_enquiry_response(struct lapb_cb *lapb, int type) +{ #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S%d TX RR(1) R%d\n", lapb->dev, lapb->state, lapb->vr); #endif - lapb_send_control(lapb, LAPB_RR, LAPB_POLLON, LAPB_RESPONSE); + lapb_send_control(lapb, LAPB_RR, LAPB_POLLON, type); lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; } @@ -197,6 +259,7 @@ void lapb_timeout_response(struct lapb_cb *lapb) { #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S%d TX RR(0) R%d\n", lapb->dev, lapb->state, lapb->vr); #endif @@ -211,6 +274,8 @@ lapb_frames_acked(lapb, nr); lapb_stop_t1timer(lapb); lapb->n2count = 0; + lapb->q921_flags &= ~LAPB_Q921_FLG_TIMER_RECOVERY; + lapb_start_t203(lapb); } else if (lapb->va != nr) { lapb_frames_acked(lapb, nr); lapb_start_t1timer(lapb); @@ -220,5 +285,14 @@ void lapb_check_need_response(struct lapb_cb *lapb, int type, int pf) { if (type == LAPB_COMMAND && pf) - lapb_enquiry_response(lapb); + lapb_enquiry_response(lapb, LAPB_RESPONSE); } + +void lapb_initialize_retransmission(struct lapb_cb *lapb) +{ + lapb_stop_t1timer(lapb); + lapb->n2count = 0; + lapb->q921_flags &= ~LAPB_Q921_FLG_TIMER_RECOVERY; + lapb_requeue_frames(lapb); + lapb_start_t203(lapb); +} Index: net/lapb/lapb_subr.c =================================================================== --- net/lapb/lapb_subr.c (revision 3155) +++ net/lapb/lapb_subr.c (working copy) @@ -89,6 +89,26 @@ */ int lapb_validate_nr(struct lapb_cb *lapb, unsigned short nr) { + /* use some if's istead of trying in a loop, to speed up the check + */ +#if 1 + /* nr must be in the valid range */ + if (nr >= + ((lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS)) { + return 0; + } + + if (lapb->vs >= lapb->va) { + /* the simple case, no wrap arround of vs */ + return ((nr >= lapb->va) && (nr <= lapb->vs)); + } else { + /* wrap arround of vs, so the valid range is va .. max and 0 .. vs + * 0 needn't to be checked, because it's unsigned and the upper limit + * is checked before + */ + return ((nr >= lapb->va) || (nr <= lapb->vs)); + } +#else unsigned short vc = lapb->va; int modulus; @@ -101,6 +121,7 @@ } return nr == lapb->vs; +#endif // if 0 } /* @@ -113,44 +134,82 @@ frame->type = LAPB_ILLEGAL; #if LAPB_DEBUG > 2 - printk(KERN_DEBUG "lapb: (%p) S%d RX %02X %02X %02X\n", - lapb->dev, lapb->state, - skb->data[0], skb->data[1], skb->data[2]); + if (lapb->mode & LAPB_Q921) { + /* struct timeval tim; + * jiffies_to_timeval(jiffies, &tim); + */ + LAPB_DEBUG_DYN_CHK(lapb, 2) + printk(KERN_DEBUG + /* "lapb: (%p) S%d Tim:%lu.%3.3lu RX %02X %02X %02X %02X\n", */ + "lapb: (%p) S%d RX %02X %02X %02X %02X\n", + lapb->dev, lapb->state, /* tim.tv_sec, tim.tv_usec / 1000, */ + skb->data[0], skb->data[1], + skb->data[2], skb->data[3]); + } else { + LAPB_DEBUG_DYN_CHK(lapb, 2) + printk(KERN_DEBUG "lapb: (%p) S%d RX %02X %02X %02X\n", + lapb->dev, lapb->state, + skb->data[0], skb->data[1], skb->data[2]); + } #endif - /* We always need to look at 2 bytes, sometimes we need - * to look at 3 and those cases are handled below. - */ - if (!pskb_may_pull(skb, 2)) - return -1; + if (lapb->mode & LAPB_Q921) { + /* We always need to look at 3 bytes, sometimes we need + * to look at 4 and those cases are handled below. + */ + if (!pskb_may_pull(skb, 3)) + return -1; - if (lapb->mode & LAPB_MLP) { - if (lapb->mode & LAPB_DCE) { - if (skb->data[0] == LAPB_ADDR_D) + if ((skb->data[0] >> 2) != lapb->sapi) + return -1; + if ((skb->data[1] & 0x01) != 0x01) + return -1; + if ((skb->data[1] >> 1) != lapb->tei) + return -1; + + frame->cr = LAPB_RESPONSE; + if (lapb->mode & LAPB_MLP) { + if ((skb->data[0] & LAPB_CMD_RESP) == 0) frame->cr = LAPB_COMMAND; - if (skb->data[0] == LAPB_ADDR_C) - frame->cr = LAPB_RESPONSE; } else { - if (skb->data[0] == LAPB_ADDR_C) + if ((skb->data[0] & LAPB_CMD_RESP) == LAPB_CMD_RESP) frame->cr = LAPB_COMMAND; - if (skb->data[0] == LAPB_ADDR_D) - frame->cr = LAPB_RESPONSE; } + skb_pull(skb, 2); } else { - if (lapb->mode & LAPB_DCE) { - if (skb->data[0] == LAPB_ADDR_B) - frame->cr = LAPB_COMMAND; - if (skb->data[0] == LAPB_ADDR_A) - frame->cr = LAPB_RESPONSE; + /* We always need to look at 2 bytes, sometimes we need + * to look at 3 and those cases are handled below. + */ + if (!pskb_may_pull(skb, 2)) + return -1; + + if (lapb->mode & LAPB_MLP) { + if (lapb->mode & LAPB_DCE) { + if (skb->data[0] == LAPB_ADDR_D) + frame->cr = LAPB_COMMAND; + if (skb->data[0] == LAPB_ADDR_C) + frame->cr = LAPB_RESPONSE; + } else { + if (skb->data[0] == LAPB_ADDR_C) + frame->cr = LAPB_COMMAND; + if (skb->data[0] == LAPB_ADDR_D) + frame->cr = LAPB_RESPONSE; + } } else { - if (skb->data[0] == LAPB_ADDR_A) - frame->cr = LAPB_COMMAND; - if (skb->data[0] == LAPB_ADDR_B) - frame->cr = LAPB_RESPONSE; + if (lapb->mode & LAPB_DCE) { + if (skb->data[0] == LAPB_ADDR_B) + frame->cr = LAPB_COMMAND; + if (skb->data[0] == LAPB_ADDR_A) + frame->cr = LAPB_RESPONSE; + } else { + if (skb->data[0] == LAPB_ADDR_A) + frame->cr = LAPB_COMMAND; + if (skb->data[0] == LAPB_ADDR_B) + frame->cr = LAPB_RESPONSE; + } } + skb_pull(skb, 1); } - - skb_pull(skb, 1); if (lapb->mode & LAPB_EXTENDED) { if (!(skb->data[0] & LAPB_S)) { @@ -232,7 +291,7 @@ struct sk_buff *skb; unsigned char *dptr; - if ((skb = alloc_skb(LAPB_HEADER_LEN + 3, GFP_ATOMIC)) == NULL) + if ((skb = alloc_skb(LAPB_HEADER_LEN + 4, GFP_ATOMIC)) == NULL) return; skb_reserve(skb, LAPB_HEADER_LEN + 1); @@ -268,7 +327,7 @@ struct sk_buff *skb; unsigned char *dptr; - if ((skb = alloc_skb(LAPB_HEADER_LEN + 7, GFP_ATOMIC)) == NULL) + if ((skb = alloc_skb(LAPB_HEADER_LEN + 8, GFP_ATOMIC)) == NULL) return; skb_reserve(skb, LAPB_HEADER_LEN + 1); @@ -286,6 +345,7 @@ *dptr++ = lapb->frmr_type; #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S%d TX FRMR %02X %02X %02X %02X %02X\n", lapb->dev, lapb->state, skb->data[1], skb->data[2], skb->data[3], @@ -303,6 +363,7 @@ *dptr++ = lapb->frmr_type; #if LAPB_DEBUG > 1 + LAPB_DEBUG_DYN_CHK(lapb, 1) printk(KERN_DEBUG "lapb: (%p) S%d TX FRMR %02X %02X %02X\n", lapb->dev, lapb->state, skb->data[1], skb->data[2], skb->data[3]); - To unsubscribe from this list: send the line "unsubscribe linux-x25" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html