Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
21035ffe
Commit
21035ffe
authored
Jun 04, 2005
by
Committed by
Jeff Garzik
Jun 04, 2005
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of /spare/repo/netdev-2.6 branch ppp
parents
14d8ce70
516cd15f
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
110 additions
and
67 deletions
+110
-67
drivers/net/ppp_generic.c
drivers/net/ppp_generic.c
+110
-67
No files found.
drivers/net/ppp_generic.c
View file @
21035ffe
...
@@ -1217,36 +1217,43 @@ ppp_push(struct ppp *ppp)
...
@@ -1217,36 +1217,43 @@ ppp_push(struct ppp *ppp)
*/
*/
static
int
ppp_mp_explode
(
struct
ppp
*
ppp
,
struct
sk_buff
*
skb
)
static
int
ppp_mp_explode
(
struct
ppp
*
ppp
,
struct
sk_buff
*
skb
)
{
{
int
nch
,
len
,
fragsize
;
int
len
,
fragsize
;
int
i
,
bits
,
hdrlen
,
mtu
;
int
i
,
bits
,
hdrlen
,
mtu
;
int
flen
,
fnb
;
int
flen
;
int
navail
,
nfree
;
int
nbigger
;
unsigned
char
*
p
,
*
q
;
unsigned
char
*
p
,
*
q
;
struct
list_head
*
list
;
struct
list_head
*
list
;
struct
channel
*
pch
;
struct
channel
*
pch
;
struct
sk_buff
*
frag
;
struct
sk_buff
*
frag
;
struct
ppp_channel
*
chan
;
struct
ppp_channel
*
chan
;
nch
=
0
;
nfree
=
0
;
/* # channels which have no packet already queued */
navail
=
0
;
/* total # of usable channels (not deregistered) */
hdrlen
=
(
ppp
->
flags
&
SC_MP_XSHORTSEQ
)
?
MPHDRLEN_SSN
:
MPHDRLEN
;
hdrlen
=
(
ppp
->
flags
&
SC_MP_XSHORTSEQ
)
?
MPHDRLEN_SSN
:
MPHDRLEN
;
i
=
0
;
list
=
&
ppp
->
channels
;
list
=
&
ppp
->
channels
;
while
((
list
=
list
->
next
)
!=
&
ppp
->
channels
)
{
while
((
list
=
list
->
next
)
!=
&
ppp
->
channels
)
{
pch
=
list_entry
(
list
,
struct
channel
,
clist
);
pch
=
list_entry
(
list
,
struct
channel
,
clist
);
nch
+=
pch
->
avail
=
(
skb_queue_len
(
&
pch
->
file
.
xq
)
==
0
);
navail
+=
pch
->
avail
=
(
pch
->
chan
!=
NULL
);
/*
if
(
pch
->
avail
)
{
* If a channel hasn't had a fragment yet, it has to get
if
(
skb_queue_len
(
&
pch
->
file
.
xq
)
==
0
* one before we send any fragments on later channels.
||
!
pch
->
had_frag
)
{
* If it can't take a fragment now, don't give any
pch
->
avail
=
2
;
* to subsequent channels.
++
nfree
;
*/
if
(
!
pch
->
had_frag
&&
!
pch
->
avail
)
{
while
((
list
=
list
->
next
)
!=
&
ppp
->
channels
)
{
pch
=
list_entry
(
list
,
struct
channel
,
clist
);
pch
->
avail
=
0
;
}
}
break
;
if
(
!
pch
->
had_frag
&&
i
<
ppp
->
nxchan
)
ppp
->
nxchan
=
i
;
}
}
++
i
;
}
}
if
(
nch
==
0
)
/*
* Don't start sending this packet unless at least half of
* the channels are free. This gives much better TCP
* performance if we have a lot of channels.
*/
if
(
nfree
==
0
||
nfree
<
navail
/
2
)
return
0
;
/* can't take now, leave it in xmit_pending */
return
0
;
/* can't take now, leave it in xmit_pending */
/* Do protocol field compression (XXX this should be optional) */
/* Do protocol field compression (XXX this should be optional) */
...
@@ -1257,14 +1264,19 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
...
@@ -1257,14 +1264,19 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
--
len
;
--
len
;
}
}
/* decide on fragment size */
/*
* Decide on fragment size.
* We create a fragment for each free channel regardless of
* how small they are (i.e. even 0 length) in order to minimize
* the time that it will take to detect when a channel drops
* a fragment.
*/
fragsize
=
len
;
fragsize
=
len
;
if
(
nch
>
1
)
{
if
(
nfree
>
1
)
int
maxch
=
ROUNDUP
(
len
,
MIN_FRAG_SIZE
);
fragsize
=
ROUNDUP
(
fragsize
,
nfree
);
if
(
nch
>
maxch
)
/* nbigger channels get fragsize bytes, the rest get fragsize-1,
nch
=
maxch
;
except if nbigger==0, then they all get fragsize. */
fragsize
=
ROUNDUP
(
fragsize
,
nch
);
nbigger
=
len
%
nfree
;
}
/* skip to the channel after the one we last used
/* skip to the channel after the one we last used
and start at that one */
and start at that one */
...
@@ -1278,7 +1290,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
...
@@ -1278,7 +1290,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
/* create a fragment for each channel */
/* create a fragment for each channel */
bits
=
B
;
bits
=
B
;
do
{
while
(
nfree
>
0
||
len
>
0
)
{
list
=
list
->
next
;
list
=
list
->
next
;
if
(
list
==
&
ppp
->
channels
)
{
if
(
list
==
&
ppp
->
channels
)
{
i
=
0
;
i
=
0
;
...
@@ -1289,61 +1301,92 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
...
@@ -1289,61 +1301,92 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
if
(
!
pch
->
avail
)
if
(
!
pch
->
avail
)
continue
;
continue
;
/*
* Skip this channel if it has a fragment pending already and
* we haven't given a fragment to all of the free channels.
*/
if
(
pch
->
avail
==
1
)
{
if
(
nfree
>
0
)
continue
;
}
else
{
--
nfree
;
pch
->
avail
=
1
;
}
/* check the channel's mtu and whether it is still attached. */
/* check the channel's mtu and whether it is still attached. */
spin_lock_bh
(
&
pch
->
downl
);
spin_lock_bh
(
&
pch
->
downl
);
if
(
pch
->
chan
==
0
||
(
mtu
=
pch
->
chan
->
mtu
)
<
hdrlen
)
{
if
(
pch
->
chan
==
NULL
)
{
/* can't use this channel */
/* can't use this channel
, it's being deregistered
*/
spin_unlock_bh
(
&
pch
->
downl
);
spin_unlock_bh
(
&
pch
->
downl
);
pch
->
avail
=
0
;
pch
->
avail
=
0
;
if
(
--
n
ch
==
0
)
if
(
--
n
avail
==
0
)
break
;
break
;
continue
;
continue
;
}
}
/*
/*
* We have to create multiple fragments for this channel
* Create a fragment for this channel of
* if fragsize is greater than the channel's mtu.
* min(max(mtu+2-hdrlen, 4), fragsize, len) bytes.
* If mtu+2-hdrlen < 4, that is a ridiculously small
* MTU, so we use mtu = 2 + hdrlen.
*/
*/
if
(
fragsize
>
len
)
if
(
fragsize
>
len
)
fragsize
=
len
;
fragsize
=
len
;
for
(
flen
=
fragsize
;
flen
>
0
;
flen
-=
fnb
)
{
flen
=
fragsize
;
fnb
=
flen
;
mtu
=
pch
->
chan
->
mtu
+
2
-
hdrlen
;
if
(
fnb
>
mtu
+
2
-
hdrlen
)
if
(
mtu
<
4
)
fnb
=
mtu
+
2
-
hdrlen
;
mtu
=
4
;
if
(
fnb
>=
len
)
if
(
flen
>
mtu
)
bits
|=
E
;
flen
=
mtu
;
frag
=
alloc_skb
(
fnb
+
hdrlen
,
GFP_ATOMIC
);
if
(
flen
==
len
&&
nfree
==
0
)
if
(
frag
==
0
)
bits
|=
E
;
goto
noskb
;
frag
=
alloc_skb
(
flen
+
hdrlen
+
(
flen
==
0
),
GFP_ATOMIC
);
q
=
skb_put
(
frag
,
fnb
+
hdrlen
);
if
(
frag
==
0
)
/* make the MP header */
goto
noskb
;
q
[
0
]
=
PPP_MP
>>
8
;
q
=
skb_put
(
frag
,
flen
+
hdrlen
);
q
[
1
]
=
PPP_MP
;
if
(
ppp
->
flags
&
SC_MP_XSHORTSEQ
)
{
/* make the MP header */
q
[
2
]
=
bits
+
((
ppp
->
nxseq
>>
8
)
&
0xf
);
q
[
0
]
=
PPP_MP
>>
8
;
q
[
3
]
=
ppp
->
nxseq
;
q
[
1
]
=
PPP_MP
;
}
else
{
if
(
ppp
->
flags
&
SC_MP_XSHORTSEQ
)
{
q
[
2
]
=
bits
;
q
[
2
]
=
bits
+
((
ppp
->
nxseq
>>
8
)
&
0xf
);
q
[
3
]
=
ppp
->
nxseq
>>
16
;
q
[
3
]
=
ppp
->
nxseq
;
q
[
4
]
=
ppp
->
nxseq
>>
8
;
}
else
{
q
[
5
]
=
ppp
->
nxseq
;
q
[
2
]
=
bits
;
}
q
[
3
]
=
ppp
->
nxseq
>>
16
;
q
[
4
]
=
ppp
->
nxseq
>>
8
;
/* copy the data in */
q
[
5
]
=
ppp
->
nxseq
;
memcpy
(
q
+
hdrlen
,
p
,
fnb
);
/* try to send it down the channel */
chan
=
pch
->
chan
;
if
(
!
chan
->
ops
->
start_xmit
(
chan
,
frag
))
skb_queue_tail
(
&
pch
->
file
.
xq
,
frag
);
pch
->
had_frag
=
1
;
p
+=
fnb
;
len
-=
fnb
;
++
ppp
->
nxseq
;
bits
=
0
;
}
}
/*
* Copy the data in.
* Unfortunately there is a bug in older versions of
* the Linux PPP multilink reconstruction code where it
* drops 0-length fragments. Therefore we make sure the
* fragment has at least one byte of data. Any bytes
* we add in this situation will end up as padding on the
* end of the reconstructed packet.
*/
if
(
flen
==
0
)
*
skb_put
(
frag
,
1
)
=
0
;
else
memcpy
(
q
+
hdrlen
,
p
,
flen
);
/* try to send it down the channel */
chan
=
pch
->
chan
;
if
(
skb_queue_len
(
&
pch
->
file
.
xq
)
||
!
chan
->
ops
->
start_xmit
(
chan
,
frag
))
skb_queue_tail
(
&
pch
->
file
.
xq
,
frag
);
pch
->
had_frag
=
1
;
p
+=
flen
;
len
-=
flen
;
++
ppp
->
nxseq
;
bits
=
0
;
spin_unlock_bh
(
&
pch
->
downl
);
spin_unlock_bh
(
&
pch
->
downl
);
}
while
(
len
>
0
);
if
(
--
nbigger
==
0
&&
fragsize
>
0
)
--
fragsize
;
}
ppp
->
nxchan
=
i
;
ppp
->
nxchan
=
i
;
return
1
;
return
1
;
...
@@ -1422,7 +1465,7 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
...
@@ -1422,7 +1465,7 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
;
return
;
}
}
proto
=
PPP_PROTO
(
skb
);
proto
=
PPP_PROTO
(
skb
);
read_lock_bh
(
&
pch
->
upl
);
read_lock_bh
(
&
pch
->
upl
);
if
(
pch
->
ppp
==
0
||
proto
>=
0xc000
||
proto
==
PPP_CCPFRAG
)
{
if
(
pch
->
ppp
==
0
||
proto
>=
0xc000
||
proto
==
PPP_CCPFRAG
)
{
...
@@ -1691,7 +1734,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
...
@@ -1691,7 +1734,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
struct
list_head
*
l
;
struct
list_head
*
l
;
int
mphdrlen
=
(
ppp
->
flags
&
SC_MP_SHORTSEQ
)
?
MPHDRLEN_SSN
:
MPHDRLEN
;
int
mphdrlen
=
(
ppp
->
flags
&
SC_MP_SHORTSEQ
)
?
MPHDRLEN_SSN
:
MPHDRLEN
;
if
(
!
pskb_may_pull
(
skb
,
mphdrlen
+
1
)
||
ppp
->
mrru
==
0
)
if
(
!
pskb_may_pull
(
skb
,
mphdrlen
)
||
ppp
->
mrru
==
0
)
goto
err
;
/* no good, throw it away */
goto
err
;
/* no good, throw it away */
/* Decode sequence number and begin/end bits */
/* Decode sequence number and begin/end bits */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment