diff mbox

[mISDN,v2,09/19] Fix TEI and SAPI handling

Message ID cbbb2723784ecf04bcec253c547a9464a2e722c7.1243024967.git.kkeil@pingi.linux-pingi.de
State Superseded, archived
Delegated to: David Miller
Headers show

Commit Message

Karsten Keil May 22, 2009, 9:04 p.m. UTC
From: Andreas Eversberg <andreas@eversberg.eu>

Added SAPI value to use SAPIs different than 0.

Now fixed TEIs work in NT mode. This allows PTP endpoint to be connected
to PTMP ports together with other PTMP endpoints.

Signed-off-by: Andreas Eversberg <andreas@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
 drivers/isdn/mISDN/layer2.c |   13 +++++++------
 drivers/isdn/mISDN/layer2.h |    2 +-
 drivers/isdn/mISDN/tei.c    |   25 ++++++++++++-------------
 3 files changed, 20 insertions(+), 20 deletions(-)

Comments

Karsten Keil May 23, 2009, 1 p.m. UTC | #1
Hi Sam,

thanks for the review.

On Freitag, 22. Mai 2009 23:53:14 Sam Ravnborg wrote:
> Hi Karsten.
>
> Flash from the past looking at some ISDN layer2.
> Some comments below.
>
> 	Sam
>
> >  struct layer2 *
> > -create_l2(struct mISDNchannel *ch, u_int protocol, u_long options,
> > u_long arg) +create_l2(struct mISDNchannel *ch, u_int protocol, u_long
> > options, u_int tei, +		u_int sapi)
>
> Unrealted to this specific patch...
> Are there any specific reason why mISDN prefer bsd style (u_int)
> rather then linux style (u32)?

No, this was some historic process with the ISDN code.
I think, if we want change this we should make a separate  patch to change 
this in all mISDN code later, I usually prefer shorter type names as well :-).
So as rule of dumb:
- Use   uN/sN for all values with constant width N ?

What should be used on functions which are usually defined as int and
only return 0 or some negative ERROR code, I think int should be OK here ?

>
> >  static struct layer2 *
> > -create_new_tei(struct manager *mgr, int tei)
> > +create_new_tei(struct manager *mgr, int tei, int sapi)
> >  {
>
> Here tei and sapi are passed as signed.
> But valid sapi range is [0..63] and tei [0..127].
> And create_l2 above uses unsigned.
>
> This looks confusing.

I think the signed was selected for error handling, but you are correct then 
it should be the same in all functions.

>
> >  	u_long		opt = 0;
> >  	u_long		flags;
> > @@ -791,7 +791,7 @@ create_new_tei(struct manager *mgr, int tei)
> >  	if (mgr->ch.st->dev->Dprotocols
> >  	  & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
> >  		test_and_set_bit(OPTION_L2_PMX, &opt);
> > -	l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, (u_int)opt, (u_long)tei);
> > +	l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, (u_int)opt, tei, sapi);
> >  	if (!l2) {
> >  		printk(KERN_WARNING "%s:no memory for layer2\n", __func__);
> >  		return NULL;
> > @@ -839,12 +839,15 @@ new_tei_req(struct manager *mgr, u_char *dp)
> >  	ri += dp[1];
> >  	if (!mgr->up)
> >  		goto denied;
> > -	tei = get_free_tei(mgr);
> > +	if (dp[3] != 0xff)
> > +		tei = dp[3] >> 1; /* 3GPP TS 08.56 6.1.11.2 */
> > +	else
> > +		tei = get_free_tei(mgr);
>
> You should check EA0 here before assuming that any values except
> EA=1, tei=127 equals ptmp.
>

make sense.

> >  	if (tei < 0) {
> >  		printk(KERN_WARNING "%s:No free tei\n", __func__);
> >  		goto denied;
> >  	}
>
> So get_free_tei() may return a negative value indicating no free tei.
> So that make my comment above void - but is this really the best way
> to return an error. Possibly it is..
>
We could define 255 as the error value, I will think about this, but in 
general I prefer negative values for error cases.

> > -	l2 = create_new_tei(mgr, tei);
> > +	l2 = create_new_tei(mgr, tei, 0);
>
> In general I would prefer to read: SAPI_CALLCONTROL rahter than a hardcoded
> 0.
>

Yes.

> >  	if (!l2)
> >  		goto denied;
> >  	else
> > @@ -976,8 +979,6 @@ create_teimgr(struct manager *mgr, struct channel_req
> > *crq) __func__, dev_name(&mgr->ch.st->dev->dev),
> >  			crq->protocol, crq->adr.dev, crq->adr.channel,
> >  			crq->adr.sapi, crq->adr.tei);
> > -	if (crq->adr.sapi != 0) /* not supported yet */
> > -		return -EINVAL;
> >  	if (crq->adr.tei > GROUP_TEI)
> >  		return -EINVAL;
> >  	if (crq->adr.tei < 64)
> > @@ -1025,7 +1026,7 @@ create_teimgr(struct manager *mgr, struct
> > channel_req *crq) return 0;
> >  	}
> >  	l2 = create_l2(crq->ch, crq->protocol, (u_int)opt,
> > -		(u_long)crq->adr.tei);
> > +		crq->adr.tei, crq->adr.sapi);
> >  	if (!l2)
> >  		return -ENOMEM;
> >  	l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL);
> > @@ -1166,7 +1167,7 @@ static int
> >  check_data(struct manager *mgr, struct sk_buff *skb)
> >  {
> >  	struct mISDNhead	*hh =  mISDN_HEAD_P(skb);
> > -	int			ret, tei;
> > +	int			ret, tei, sapi;
> >  	struct layer2		*l2;
> >
> >  	if (*debug & DEBUG_L2_CTRL)
> > @@ -1178,18 +1179,16 @@ check_data(struct manager *mgr, struct sk_buff
> > *skb) return -ENOTCONN;
> >  	if (skb->len != 3)
> >  		return -ENOTCONN;
> > -	if (skb->data[0] != 0)
> > -		/* only SAPI 0 command */
> > -		return -ENOTCONN;
> > +	sapi = skb->data[0] >> 2;
>
> PReviously there was an implicit check of EA0.
> This is missed not that you read sapi and discard the two lower bits.
>
> I also wonder if you remeber to check the command/response bit.
> That was implicitly tested to be 0 before and also ignored now.

Yes,  you are correct.

>
> >  	if (!(skb->data[1] & 1)) /* invalid EA1 */
> >  		return -EINVAL;
> > -	tei = skb->data[1] >> 0;
> > +	tei = skb->data[1] >> 1;
>
> This looks like a bug-fix...
>

Yes,  I think fixed TEI was never tested with P2MP,  I know
no device which really use it with SAPI 0, only in P2P we use a
fixed TEI  of 0.  Also the test suite used by certifications did
not check for correct fixed TEI handling, it only checks that a
fixed TEI is rejected in a dynamic TEI assignment.
With SAPI != 0 fixed TEIs are more common, so the bug was
detected now.

> >  	if (tei > 63) /* not a fixed tei */
> >  		return -ENOTCONN;
> >  	if ((skb->data[2] & ~0x10) != SABME)
> >  		return -ENOTCONN;
> >  	/* We got a SABME for a fixed TEI */
> > -	l2 = create_new_tei(mgr, tei);
> > +	l2 = create_new_tei(mgr, tei, sapi);
> >  	if (!l2)
> >  		return -ENOMEM;
> >  	ret = l2->ch.send(&l2->ch, skb);


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sam Ravnborg May 23, 2009, 11:10 p.m. UTC | #2
> >
> > Unrealted to this specific patch...
> > Are there any specific reason why mISDN prefer bsd style (u_int)
> > rather then linux style (u32)?
> 
> No, this was some historic process with the ISDN code.
> I think, if we want change this we should make a separate  patch to change 
> this in all mISDN code later, I usually prefer shorter type names as well :-).
> So as rule of dumb:
> - Use   uN/sN for all values with constant width N ?
yes

> What should be used on functions which are usually defined as int and
> only return 0 or some negative ERROR code, I think int should be OK here ?
yes - use int here.

> > >  static struct layer2 *
> > > -create_new_tei(struct manager *mgr, int tei)
> > > +create_new_tei(struct manager *mgr, int tei, int sapi)
> > >  {
> >
> > Here tei and sapi are passed as signed.
> > But valid sapi range is [0..63] and tei [0..127].
> > And create_l2 above uses unsigned.
> >
> > This looks confusing.
> 
> I think the signed was selected for error handling, but you are correct then 
> it should be the same in all functions.
The correct values are the range [0..127] so as you also imply
reserving all negative values for error codes seems like the best choice.

So as a matter of consistency you should use int for tei/sapi all over.
> >
> > So get_free_tei() may return a negative value indicating no free tei.
> > So that make my comment above void - but is this really the best way
> > to return an error. Possibly it is..
> >
> We could define 255 as the error value, I will think about this, but in 
> general I prefer negative values for error cases.

Addressed above - agree.

> > >  	if (!(skb->data[1] & 1)) /* invalid EA1 */
> > >  		return -EINVAL;
> > > -	tei = skb->data[1] >> 0;
> > > +	tei = skb->data[1] >> 1;
> >
> > This looks like a bug-fix...
> >
> 
> Yes,  I think fixed TEI was never tested with P2MP,  I know
> no device which really use it with SAPI 0, only in P2P we use a
> fixed TEI  of 0.  Also the test suite used by certifications did
> not check for correct fixed TEI handling, it only checks that a
> fixed TEI is rejected in a dynamic TEI assignment.
> With SAPI != 0 fixed TEIs are more common, so the bug was
> detected now.
Yep - I know we used fixed tei in ptmp configuration
for sapi=16 (packet handling aka X.25 over ISDN).

	Sam
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index d6e2863..0628ef6 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -2068,7 +2068,8 @@  l2_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
 }
 
 struct layer2 *
-create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
+create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_int tei,
+		u_int sapi)
 {
 	struct layer2		*l2;
 	struct channel_req	rq;
@@ -2089,7 +2090,7 @@  create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
 		test_and_set_bit(FLG_LAPD, &l2->flag);
 		test_and_set_bit(FLG_LAPD_NET, &l2->flag);
 		test_and_set_bit(FLG_MOD128, &l2->flag);
-		l2->sapi = 0;
+		l2->sapi = sapi;
 		l2->maxlen = MAX_DFRAME_LEN;
 		if (test_bit(OPTION_L2_PMX, &options))
 			l2->window = 7;
@@ -2099,7 +2100,7 @@  create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
 			test_and_set_bit(FLG_PTP, &l2->flag);
 		if (test_bit(OPTION_L2_FIXEDTEI, &options))
 			test_and_set_bit(FLG_FIXED_TEI, &l2->flag);
-		l2->tei = (u_int)arg;
+		l2->tei = tei;
 		l2->T200 = 1000;
 		l2->N200 = 3;
 		l2->T203 = 10000;
@@ -2114,7 +2115,7 @@  create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
 		test_and_set_bit(FLG_LAPD, &l2->flag);
 		test_and_set_bit(FLG_MOD128, &l2->flag);
 		test_and_set_bit(FLG_ORIG, &l2->flag);
-		l2->sapi = 0;
+		l2->sapi = sapi;
 		l2->maxlen = MAX_DFRAME_LEN;
 		if (test_bit(OPTION_L2_PMX, &options))
 			l2->window = 7;
@@ -2124,7 +2125,7 @@  create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
 			test_and_set_bit(FLG_PTP, &l2->flag);
 		if (test_bit(OPTION_L2_FIXEDTEI, &options))
 			test_and_set_bit(FLG_FIXED_TEI, &l2->flag);
-		l2->tei = (u_int)arg;
+		l2->tei = tei;
 		l2->T200 = 1000;
 		l2->N200 = 3;
 		l2->T203 = 10000;
@@ -2180,7 +2181,7 @@  x75create(struct channel_req *crq)
 
 	if (crq->protocol != ISDN_P_B_X75SLP)
 		return -EPROTONOSUPPORT;
-	l2 = create_l2(crq->ch, crq->protocol, 0, 0);
+	l2 = create_l2(crq->ch, crq->protocol, 0, 0, 0);
 	if (!l2)
 		return -ENOMEM;
 	crq->ch = &l2->ch;
diff --git a/drivers/isdn/mISDN/layer2.h b/drivers/isdn/mISDN/layer2.h
index 6293f80..a85984e 100644
--- a/drivers/isdn/mISDN/layer2.h
+++ b/drivers/isdn/mISDN/layer2.h
@@ -90,7 +90,7 @@  enum {
 #define L2_STATE_COUNT (ST_L2_8+1)
 
 extern struct layer2	*create_l2(struct mISDNchannel *, u_int,
-				u_long, u_long);
+				u_long, u_int, u_int);
 extern int		tei_l2(struct layer2 *, u_int, u_long arg);
 
 
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index c75af76..9e88135 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -777,7 +777,7 @@  tei_ph_data_ind(struct teimgr *tm, u_int mt, u_char *dp, int len)
 }
 
 static struct layer2 *
-create_new_tei(struct manager *mgr, int tei)
+create_new_tei(struct manager *mgr, int tei, int sapi)
 {
 	u_long		opt = 0;
 	u_long		flags;
@@ -791,7 +791,7 @@  create_new_tei(struct manager *mgr, int tei)
 	if (mgr->ch.st->dev->Dprotocols
 	  & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
 		test_and_set_bit(OPTION_L2_PMX, &opt);
-	l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, (u_int)opt, (u_long)tei);
+	l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, (u_int)opt, tei, sapi);
 	if (!l2) {
 		printk(KERN_WARNING "%s:no memory for layer2\n", __func__);
 		return NULL;
@@ -839,12 +839,15 @@  new_tei_req(struct manager *mgr, u_char *dp)
 	ri += dp[1];
 	if (!mgr->up)
 		goto denied;
-	tei = get_free_tei(mgr);
+	if (dp[3] != 0xff)
+		tei = dp[3] >> 1; /* 3GPP TS 08.56 6.1.11.2 */
+	else
+		tei = get_free_tei(mgr);
 	if (tei < 0) {
 		printk(KERN_WARNING "%s:No free tei\n", __func__);
 		goto denied;
 	}
-	l2 = create_new_tei(mgr, tei);
+	l2 = create_new_tei(mgr, tei, 0);
 	if (!l2)
 		goto denied;
 	else
@@ -976,8 +979,6 @@  create_teimgr(struct manager *mgr, struct channel_req *crq)
 			__func__, dev_name(&mgr->ch.st->dev->dev),
 			crq->protocol, crq->adr.dev, crq->adr.channel,
 			crq->adr.sapi, crq->adr.tei);
-	if (crq->adr.sapi != 0) /* not supported yet */
-		return -EINVAL;
 	if (crq->adr.tei > GROUP_TEI)
 		return -EINVAL;
 	if (crq->adr.tei < 64)
@@ -1025,7 +1026,7 @@  create_teimgr(struct manager *mgr, struct channel_req *crq)
 		return 0;
 	}
 	l2 = create_l2(crq->ch, crq->protocol, (u_int)opt,
-		(u_long)crq->adr.tei);
+		crq->adr.tei, crq->adr.sapi);
 	if (!l2)
 		return -ENOMEM;
 	l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL);
@@ -1166,7 +1167,7 @@  static int
 check_data(struct manager *mgr, struct sk_buff *skb)
 {
 	struct mISDNhead	*hh =  mISDN_HEAD_P(skb);
-	int			ret, tei;
+	int			ret, tei, sapi;
 	struct layer2		*l2;
 
 	if (*debug & DEBUG_L2_CTRL)
@@ -1178,18 +1179,16 @@  check_data(struct manager *mgr, struct sk_buff *skb)
 		return -ENOTCONN;
 	if (skb->len != 3)
 		return -ENOTCONN;
-	if (skb->data[0] != 0)
-		/* only SAPI 0 command */
-		return -ENOTCONN;
+	sapi = skb->data[0] >> 2;
 	if (!(skb->data[1] & 1)) /* invalid EA1 */
 		return -EINVAL;
-	tei = skb->data[1] >> 0;
+	tei = skb->data[1] >> 1;
 	if (tei > 63) /* not a fixed tei */
 		return -ENOTCONN;
 	if ((skb->data[2] & ~0x10) != SABME)
 		return -ENOTCONN;
 	/* We got a SABME for a fixed TEI */
-	l2 = create_new_tei(mgr, tei);
+	l2 = create_new_tei(mgr, tei, sapi);
 	if (!l2)
 		return -ENOMEM;
 	ret = l2->ch.send(&l2->ch, skb);