[PATCH 2.6.19.2] net/lapb: ITU-T Q.921 mode implemented

From: JESSICH Jasmin
Date: Fri Apr 27 2007 - 14:55:48 EST


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-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/