Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
38783e67
K
Kernel
项目概览
openeuler
/
Kernel
大约 1 年 前同步成功
通知
6
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
38783e67
编写于
9月 22, 2008
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
isdn: isdn_ppp: Use SKB list facilities instead of home-grown implementation.
Signed-off-by:
N
David S. Miller
<
davem@davemloft.net
>
上级
8fc5387c
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
190 addition
and
164 deletion
+190
-164
drivers/isdn/i4l/isdn_ppp.c
drivers/isdn/i4l/isdn_ppp.c
+189
-163
include/linux/isdn_ppp.h
include/linux/isdn_ppp.h
+1
-1
未找到文件。
drivers/isdn/i4l/isdn_ppp.c
浏览文件 @
38783e67
...
@@ -1533,8 +1533,10 @@ static int isdn_ppp_mp_bundle_array_init(void)
...
@@ -1533,8 +1533,10 @@ static int isdn_ppp_mp_bundle_array_init(void)
int
sz
=
ISDN_MAX_CHANNELS
*
sizeof
(
ippp_bundle
);
int
sz
=
ISDN_MAX_CHANNELS
*
sizeof
(
ippp_bundle
);
if
(
(
isdn_ppp_bundle_arr
=
kzalloc
(
sz
,
GFP_KERNEL
))
==
NULL
)
if
(
(
isdn_ppp_bundle_arr
=
kzalloc
(
sz
,
GFP_KERNEL
))
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
spin_lock_init
(
&
isdn_ppp_bundle_arr
[
i
].
lock
);
spin_lock_init
(
&
isdn_ppp_bundle_arr
[
i
].
lock
);
skb_queue_head_init
(
&
isdn_ppp_bundle_arr
[
i
].
frags
);
}
return
0
;
return
0
;
}
}
...
@@ -1567,7 +1569,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
...
@@ -1567,7 +1569,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
if
((
lp
->
netdev
->
pb
=
isdn_ppp_mp_bundle_alloc
())
==
NULL
)
if
((
lp
->
netdev
->
pb
=
isdn_ppp_mp_bundle_alloc
())
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
lp
->
next
=
lp
->
last
=
lp
;
/* nobody else in a queue */
lp
->
next
=
lp
->
last
=
lp
;
/* nobody else in a queue */
lp
->
netdev
->
pb
->
frags
=
NULL
;
skb_queue_head_init
(
&
lp
->
netdev
->
pb
->
frags
)
;
lp
->
netdev
->
pb
->
frames
=
0
;
lp
->
netdev
->
pb
->
frames
=
0
;
lp
->
netdev
->
pb
->
seq
=
UINT_MAX
;
lp
->
netdev
->
pb
->
seq
=
UINT_MAX
;
}
}
...
@@ -1579,28 +1581,29 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
...
@@ -1579,28 +1581,29 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
static
u32
isdn_ppp_mp_get_seq
(
int
short_seq
,
static
u32
isdn_ppp_mp_get_seq
(
int
short_seq
,
struct
sk_buff
*
skb
,
u32
last_seq
);
struct
sk_buff
*
skb
,
u32
last_seq
);
static
struct
sk_buff
*
isdn_ppp_mp_discard
(
ippp_bundle
*
mp
,
static
void
isdn_ppp_mp_discard
(
ippp_bundle
*
mp
,
struct
sk_buff
*
from
,
struct
sk_buff
*
from
,
struct
sk_buff
*
to
);
struct
sk_buff
*
to
);
static
void
isdn_ppp_mp_reassembly
(
isdn_net_dev
*
net_dev
,
isdn_net_local
*
lp
,
static
void
isdn_ppp_mp_reassembly
(
isdn_net_dev
*
net_dev
,
isdn_net_local
*
lp
,
struct
sk_buff
*
from
,
struct
sk_buff
*
to
);
struct
sk_buff
*
from
,
struct
sk_buff
*
to
,
static
void
isdn_ppp_mp_free_skb
(
ippp_bundle
*
mp
,
struct
sk_buff
*
skb
);
u32
lastseq
);
static
void
isdn_ppp_mp_free_skb
(
ippp_bundle
*
mp
,
struct
sk_buff
*
skb
);
static
void
isdn_ppp_mp_print_recv_pkt
(
int
slot
,
struct
sk_buff
*
skb
);
static
void
isdn_ppp_mp_print_recv_pkt
(
int
slot
,
struct
sk_buff
*
skb
);
static
void
isdn_ppp_mp_receive
(
isdn_net_dev
*
net_dev
,
isdn_net_local
*
lp
,
static
void
isdn_ppp_mp_receive
(
isdn_net_dev
*
net_dev
,
isdn_net_local
*
lp
,
struct
sk_buff
*
skb
)
struct
sk_buff
*
skb
)
{
{
struct
ippp_struct
*
is
;
struct
sk_buff
*
newfrag
,
*
frag
,
*
start
,
*
nextf
;
isdn_net_local
*
lpq
;
ippp_bundle
*
mp
;
isdn_mppp_stats
*
stats
;
struct
sk_buff
*
newfrag
,
*
frag
,
*
start
,
*
nextf
;
u32
newseq
,
minseq
,
thisseq
;
u32
newseq
,
minseq
,
thisseq
;
isdn_mppp_stats
*
stats
;
struct
ippp_struct
*
is
;
unsigned
long
flags
;
unsigned
long
flags
;
isdn_net_local
*
lpq
;
ippp_bundle
*
mp
;
int
slot
;
int
slot
;
spin_lock_irqsave
(
&
net_dev
->
pb
->
lock
,
flags
);
spin_lock_irqsave
(
&
net_dev
->
pb
->
lock
,
flags
);
mp
=
net_dev
->
pb
;
mp
=
net_dev
->
pb
;
stats
=
&
mp
->
stats
;
stats
=
&
mp
->
stats
;
slot
=
lp
->
ppp_slot
;
slot
=
lp
->
ppp_slot
;
if
(
slot
<
0
||
slot
>=
ISDN_MAX_CHANNELS
)
{
if
(
slot
<
0
||
slot
>=
ISDN_MAX_CHANNELS
)
{
printk
(
KERN_ERR
"%s: lp->ppp_slot(%d)
\n
"
,
printk
(
KERN_ERR
"%s: lp->ppp_slot(%d)
\n
"
,
...
@@ -1611,20 +1614,19 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
...
@@ -1611,20 +1614,19 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
return
;
return
;
}
}
is
=
ippp_table
[
slot
];
is
=
ippp_table
[
slot
];
if
(
++
mp
->
frames
>
stats
->
max_queue_len
)
if
(
++
mp
->
frames
>
stats
->
max_queue_len
)
stats
->
max_queue_len
=
mp
->
frames
;
stats
->
max_queue_len
=
mp
->
frames
;
if
(
is
->
debug
&
0x8
)
if
(
is
->
debug
&
0x8
)
isdn_ppp_mp_print_recv_pkt
(
lp
->
ppp_slot
,
skb
);
isdn_ppp_mp_print_recv_pkt
(
lp
->
ppp_slot
,
skb
);
newseq
=
isdn_ppp_mp_get_seq
(
is
->
mpppcfg
&
SC_IN_SHORT_SEQ
,
newseq
=
isdn_ppp_mp_get_seq
(
is
->
mpppcfg
&
SC_IN_SHORT_SEQ
,
skb
,
is
->
last_link_seqno
);
skb
,
is
->
last_link_seqno
);
/* if this packet seq # is less than last already processed one,
/* if this packet seq # is less than last already processed one,
* toss it right away, but check for sequence start case first
* toss it right away, but check for sequence start case first
*/
*/
if
(
mp
->
seq
>
MP_LONGSEQ_MAX
&&
(
newseq
&
MP_LONGSEQ_MAXBIT
)
)
{
if
(
mp
->
seq
>
MP_LONGSEQ_MAX
&&
(
newseq
&
MP_LONGSEQ_MAXBIT
)
)
{
mp
->
seq
=
newseq
;
/* the first packet: required for
mp
->
seq
=
newseq
;
/* the first packet: required for
* rfc1990 non-compliant clients --
* rfc1990 non-compliant clients --
* prevents constant packet toss */
* prevents constant packet toss */
...
@@ -1634,7 +1636,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
...
@@ -1634,7 +1636,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
spin_unlock_irqrestore
(
&
mp
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
mp
->
lock
,
flags
);
return
;
return
;
}
}
/* find the minimum received sequence number over all links */
/* find the minimum received sequence number over all links */
is
->
last_link_seqno
=
minseq
=
newseq
;
is
->
last_link_seqno
=
minseq
=
newseq
;
for
(
lpq
=
net_dev
->
queue
;;)
{
for
(
lpq
=
net_dev
->
queue
;;)
{
...
@@ -1655,22 +1657,31 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
...
@@ -1655,22 +1657,31 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* packets */
* packets */
newfrag
=
skb
;
newfrag
=
skb
;
/* if this new fragment is before the first one, then enqueue it now. */
/* Insert new fragment into the proper sequence slot. */
if
((
frag
=
mp
->
frags
)
==
NULL
||
MP_LT
(
newseq
,
MP_SEQ
(
frag
)))
{
skb_queue_walk
(
&
mp
->
frags
,
frag
)
{
newfrag
->
next
=
frag
;
if
(
MP_SEQ
(
frag
)
==
newseq
)
{
mp
->
frags
=
frag
=
newfrag
;
isdn_ppp_mp_free_skb
(
mp
,
newfrag
);
newfrag
=
NULL
;
newfrag
=
NULL
;
}
break
;
}
if
(
MP_LT
(
newseq
,
MP_SEQ
(
frag
)))
{
__skb_queue_before
(
&
mp
->
frags
,
frag
,
newfrag
);
newfrag
=
NULL
;
break
;
}
}
if
(
newfrag
)
__skb_queue_tail
(
&
mp
->
frags
,
newfrag
);
start
=
MP_FLAGS
(
frag
)
&
MP_BEGIN_FRAG
&&
frag
=
skb_peek
(
&
mp
->
frags
);
MP_SEQ
(
frag
)
==
mp
->
seq
?
frag
:
NULL
;
start
=
((
MP_FLAGS
(
frag
)
&
MP_BEGIN_FRAG
)
&&
(
MP_SEQ
(
frag
)
==
mp
->
seq
))
?
frag
:
NULL
;
if
(
!
start
)
goto
check_overflow
;
/*
/* main fragment traversing loop
* main fragment traversing loop
*
*
* try to accomplish several tasks:
* try to accomplish several tasks:
* - insert new fragment into the proper sequence slot (once that's done
* newfrag will be set to NULL)
* - reassemble any complete fragment sequence (non-null 'start'
* - reassemble any complete fragment sequence (non-null 'start'
* indicates there is a continguous sequence present)
* indicates there is a continguous sequence present)
* - discard any incomplete sequences that are below minseq -- due
* - discard any incomplete sequences that are below minseq -- due
...
@@ -1679,71 +1690,46 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
...
@@ -1679,71 +1690,46 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* come to complete such sequence and it should be discarded
* come to complete such sequence and it should be discarded
*
*
* loop completes when we accomplished the following tasks:
* loop completes when we accomplished the following tasks:
* - new fragment is inserted in the proper sequence ('newfrag' is
* set to NULL)
* - we hit a gap in the sequence, so no reassembly/processing is
* - we hit a gap in the sequence, so no reassembly/processing is
* possible ('start' would be set to NULL)
* possible ('start' would be set to NULL)
*
*
* algorithm for this code is derived from code in the book
* algorithm for this code is derived from code in the book
* 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
* 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
*/
*/
while
(
start
!=
NULL
||
newfrag
!=
NULL
)
{
skb_queue_walk_safe
(
&
mp
->
frags
,
frag
,
nextf
)
{
thisseq
=
MP_SEQ
(
frag
);
thisseq
=
MP_SEQ
(
frag
);
nextf
=
frag
->
next
;
/* check for misplaced start */
if
(
start
!=
frag
&&
(
MP_FLAGS
(
frag
)
&
MP_BEGIN_FRAG
))
{
/* drop any duplicate fragments */
printk
(
KERN_WARNING
"isdn_mppp(seq %d): new "
if
(
newfrag
!=
NULL
&&
thisseq
==
newseq
)
{
"BEGIN flag with no prior END"
,
thisseq
);
isdn_ppp_mp_free_skb
(
mp
,
newfrag
);
stats
->
seqerrs
++
;
newfrag
=
NULL
;
stats
->
frame_drops
++
;
}
isdn_ppp_mp_discard
(
mp
,
start
,
frag
);
start
=
frag
;
/* insert new fragment before next element if possible. */
}
else
if
(
MP_LE
(
thisseq
,
minseq
))
{
if
(
newfrag
!=
NULL
&&
(
nextf
==
NULL
||
if
(
MP_FLAGS
(
frag
)
&
MP_BEGIN_FRAG
)
MP_LT
(
newseq
,
MP_SEQ
(
nextf
))))
{
newfrag
->
next
=
nextf
;
frag
->
next
=
nextf
=
newfrag
;
newfrag
=
NULL
;
}
if
(
start
!=
NULL
)
{
/* check for misplaced start */
if
(
start
!=
frag
&&
(
MP_FLAGS
(
frag
)
&
MP_BEGIN_FRAG
))
{
printk
(
KERN_WARNING
"isdn_mppp(seq %d): new "
"BEGIN flag with no prior END"
,
thisseq
);
stats
->
seqerrs
++
;
stats
->
frame_drops
++
;
start
=
isdn_ppp_mp_discard
(
mp
,
start
,
frag
);
nextf
=
frag
->
next
;
}
}
else
if
(
MP_LE
(
thisseq
,
minseq
))
{
if
(
MP_FLAGS
(
frag
)
&
MP_BEGIN_FRAG
)
start
=
frag
;
start
=
frag
;
else
{
else
{
if
(
MP_FLAGS
(
frag
)
&
MP_END_FRAG
)
if
(
MP_FLAGS
(
frag
)
&
MP_END_FRAG
)
stats
->
frame_drops
++
;
stats
->
frame_drops
++
;
if
(
mp
->
frags
==
frag
)
__skb_unlink
(
skb
,
&
mp
->
frags
);
mp
->
frags
=
nextf
;
isdn_ppp_mp_free_skb
(
mp
,
frag
);
isdn_ppp_mp_free_skb
(
mp
,
frag
);
frag
=
nextf
;
continue
;
continue
;
}
}
}
}
/* if start is non-null and we have end fragment, then
/* if we have end fragment, then we have full reassembly
* we have full reassembly sequence -- reassemble
* sequence -- reassemble and process packet now
* and process packet now
*/
*/
if
(
start
!=
NULL
&&
(
MP_FLAGS
(
frag
)
&
MP_END_FRAG
))
{
if
(
MP_FLAGS
(
frag
)
&
MP_END_FRAG
)
{
minseq
=
mp
->
seq
=
(
thisseq
+
1
)
&
MP_LONGSEQ_MASK
;
minseq
=
mp
->
seq
=
(
thisseq
+
1
)
&
MP_LONGSEQ_MASK
;
/* Reassemble the packet then dispatch it */
/* Reassemble the packet then dispatch it */
isdn_ppp_mp_reassembly
(
net_dev
,
lp
,
start
,
nextf
);
isdn_ppp_mp_reassembly
(
net_dev
,
lp
,
start
,
frag
,
thisseq
);
start
=
NULL
;
frag
=
NULL
;
mp
->
frags
=
nextf
;
start
=
NULL
;
}
frag
=
NULL
;
}
/* check if need to update start pointer: if we just
/* check if need to update start pointer: if we just
* reassembled the packet and sequence is contiguous
* reassembled the packet and sequence is contiguous
...
@@ -1754,26 +1740,25 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
...
@@ -1754,26 +1740,25 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* below low watermark and set start to the next frag or
* below low watermark and set start to the next frag or
* clear start ptr.
* clear start ptr.
*/
*/
if
(
nextf
!=
NULL
&&
if
(
nextf
!=
(
struct
sk_buff
*
)
&
mp
->
frags
&&
((
thisseq
+
1
)
&
MP_LONGSEQ_MASK
)
==
MP_SEQ
(
nextf
))
{
((
thisseq
+
1
)
&
MP_LONGSEQ_MASK
)
==
MP_SEQ
(
nextf
))
{
/* if we just reassembled and the next one is here,
/* if we just reassembled and the next one is here,
* then start another reassembly.
*/
* then start another reassembly.
*/
if
(
frag
==
NULL
)
{
if
(
frag
==
NULL
)
{
if
(
MP_FLAGS
(
nextf
)
&
MP_BEGIN_FRAG
)
if
(
MP_FLAGS
(
nextf
)
&
MP_BEGIN_FRAG
)
start
=
nextf
;
start
=
nextf
;
else
else
{
{
printk
(
KERN_WARNING
"isdn_mppp(seq %d):"
printk
(
KERN_WARNING
"isdn_mppp(seq %d):"
" END flag with no following "
" END flag with no following "
"BEGIN"
,
thisseq
);
"BEGIN"
,
thisseq
);
stats
->
seqerrs
++
;
stats
->
seqerrs
++
;
}
}
}
}
}
else
{
}
else
{
if
(
nextf
!=
(
struct
sk_buff
*
)
&
mp
->
frags
&&
if
(
nextf
!=
NULL
&&
frag
!=
NULL
&&
frag
!=
NULL
&&
MP_LT
(
thisseq
,
minseq
))
{
MP_LT
(
thisseq
,
minseq
))
{
/* we've got a break in the sequence
/* we've got a break in the sequence
* and we not at the end yet
* and we not at the end yet
* and we did not just reassembled
* and we did not just reassembled
...
@@ -1782,41 +1767,39 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
...
@@ -1782,41 +1767,39 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* discard all the frames below low watermark
* discard all the frames below low watermark
* and start over */
* and start over */
stats
->
frame_drops
++
;
stats
->
frame_drops
++
;
mp
->
frags
=
isdn_ppp_mp_discard
(
mp
,
start
,
nextf
);
isdn_ppp_mp_discard
(
mp
,
start
,
nextf
);
}
}
/* break in the sequence, no reassembly */
/* break in the sequence, no reassembly */
start
=
NULL
;
start
=
NULL
;
}
}
if
(
!
start
)
frag
=
nextf
;
break
;
}
/* while -- main loop */
}
if
(
mp
->
frags
==
NULL
)
check_overflow:
mp
->
frags
=
frag
;
/* rather straighforward way to deal with (not very) possible
/* rather straighforward way to deal with (not very) possible
* queue overflow */
* queue overflow
*/
if
(
mp
->
frames
>
MP_MAX_QUEUE_LEN
)
{
if
(
mp
->
frames
>
MP_MAX_QUEUE_LEN
)
{
stats
->
overflows
++
;
stats
->
overflows
++
;
while
(
mp
->
frames
>
MP_MAX_QUEUE_LEN
)
{
skb_queue_walk_safe
(
&
mp
->
frags
,
frag
,
nextf
)
{
frag
=
mp
->
frags
->
next
;
if
(
mp
->
frames
<=
MP_MAX_QUEUE_LEN
)
isdn_ppp_mp_free_skb
(
mp
,
mp
->
frags
);
break
;
mp
->
frags
=
frag
;
__skb_unlink
(
frag
,
&
mp
->
frags
);
isdn_ppp_mp_free_skb
(
mp
,
frag
);
}
}
}
}
spin_unlock_irqrestore
(
&
mp
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
mp
->
lock
,
flags
);
}
}
static
void
isdn_ppp_mp_cleanup
(
isdn_net_local
*
lp
)
static
void
isdn_ppp_mp_cleanup
(
isdn_net_local
*
lp
)
{
{
struct
sk_buff
*
frag
=
lp
->
netdev
->
pb
->
frags
;
struct
sk_buff
*
skb
,
*
tmp
;
struct
sk_buff
*
nextfrag
;
while
(
frag
)
{
skb_queue_walk_safe
(
&
lp
->
netdev
->
pb
->
frags
,
skb
,
tmp
)
{
nextfrag
=
frag
->
next
;
__skb_unlink
(
skb
,
&
lp
->
netdev
->
pb
->
frags
);
isdn_ppp_mp_free_skb
(
lp
->
netdev
->
pb
,
frag
);
isdn_ppp_mp_free_skb
(
lp
->
netdev
->
pb
,
skb
);
frag
=
nextfrag
;
}
}
lp
->
netdev
->
pb
->
frags
=
NULL
;
}
}
static
u32
isdn_ppp_mp_get_seq
(
int
short_seq
,
static
u32
isdn_ppp_mp_get_seq
(
int
short_seq
,
...
@@ -1853,72 +1836,115 @@ static u32 isdn_ppp_mp_get_seq( int short_seq,
...
@@ -1853,72 +1836,115 @@ static u32 isdn_ppp_mp_get_seq( int short_seq,
return
seq
;
return
seq
;
}
}
st
ruct
sk_buff
*
isdn_ppp_mp_discard
(
ippp_bundle
*
mp
,
st
atic
void
isdn_ppp_mp_discard
(
ippp_bundle
*
mp
,
struct
sk_buff
*
from
,
struct
sk_buff
*
from
,
struct
sk_buff
*
to
)
struct
sk_buff
*
to
)
{
{
if
(
from
)
if
(
from
)
{
while
(
from
!=
to
)
{
struct
sk_buff
*
skb
,
*
tmp
;
struct
sk_buff
*
next
=
from
->
next
;
int
freeing
=
0
;
isdn_ppp_mp_free_skb
(
mp
,
from
);
from
=
next
;
skb_queue_walk_safe
(
&
mp
->
frags
,
skb
,
tmp
)
{
if
(
skb
==
to
)
break
;
if
(
skb
==
from
)
freeing
=
1
;
if
(
!
freeing
)
continue
;
__skb_unlink
(
skb
,
&
mp
->
frags
);
isdn_ppp_mp_free_skb
(
mp
,
skb
);
}
}
return
from
;
}
}
}
void
isdn_ppp_mp_reassembly
(
isdn_net_dev
*
net_dev
,
isdn_net_local
*
lp
,
static
unsigned
int
calc_tot_len
(
struct
sk_buff_head
*
queue
,
struct
sk_buff
*
from
,
struct
sk_buff
*
to
)
struct
sk_buff
*
from
,
struct
sk_buff
*
to
)
{
{
ippp_bundle
*
mp
=
net_dev
->
pb
;
unsigned
int
tot_len
=
0
;
int
proto
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
int
found_start
=
0
;
skb_queue_walk
(
queue
,
skb
)
{
if
(
skb
==
from
)
found_start
=
1
;
if
(
!
found_start
)
continue
;
tot_len
+=
skb
->
len
-
MP_HEADER_LEN
;
if
(
skb
==
to
)
break
;
}
return
tot_len
;
}
/* Reassemble packet using fragments in the reassembly queue from
* 'from' until 'to', inclusive.
*/
static
void
isdn_ppp_mp_reassembly
(
isdn_net_dev
*
net_dev
,
isdn_net_local
*
lp
,
struct
sk_buff
*
from
,
struct
sk_buff
*
to
,
u32
lastseq
)
{
ippp_bundle
*
mp
=
net_dev
->
pb
;
unsigned
int
tot_len
;
unsigned
int
tot_len
;
struct
sk_buff
*
skb
;
int
proto
;
if
(
lp
->
ppp_slot
<
0
||
lp
->
ppp_slot
>=
ISDN_MAX_CHANNELS
)
{
if
(
lp
->
ppp_slot
<
0
||
lp
->
ppp_slot
>=
ISDN_MAX_CHANNELS
)
{
printk
(
KERN_ERR
"%s: lp->ppp_slot(%d) out of range
\n
"
,
printk
(
KERN_ERR
"%s: lp->ppp_slot(%d) out of range
\n
"
,
__func__
,
lp
->
ppp_slot
);
__func__
,
lp
->
ppp_slot
);
return
;
return
;
}
}
if
(
MP_FLAGS
(
from
)
==
(
MP_BEGIN_FRAG
|
MP_END_FRAG
)
)
{
if
(
ippp_table
[
lp
->
ppp_slot
]
->
debug
&
0x40
)
tot_len
=
calc_tot_len
(
&
mp
->
frags
,
from
,
to
);
if
(
MP_FLAGS
(
from
)
==
(
MP_BEGIN_FRAG
|
MP_END_FRAG
))
{
if
(
ippp_table
[
lp
->
ppp_slot
]
->
debug
&
0x40
)
printk
(
KERN_DEBUG
"isdn_mppp: reassembly: frame %d, "
printk
(
KERN_DEBUG
"isdn_mppp: reassembly: frame %d, "
"len %d
\n
"
,
MP_SEQ
(
from
),
from
->
len
);
"len %d
\n
"
,
MP_SEQ
(
from
),
from
->
len
);
skb
=
from
;
skb
=
from
;
skb_pull
(
skb
,
MP_HEADER_LEN
);
skb_pull
(
skb
,
MP_HEADER_LEN
);
__skb_unlink
(
skb
,
&
mp
->
frags
);
mp
->
frames
--
;
mp
->
frames
--
;
}
else
{
}
else
{
struct
sk_buff
*
frag
;
struct
sk_buff
*
walk
,
*
tmp
;
int
n
;
int
found_start
=
0
;
for
(
tot_len
=
n
=
0
,
frag
=
from
;
frag
!=
to
;
frag
=
frag
->
next
,
n
++
)
if
(
ippp_table
[
lp
->
ppp_slot
]
->
debug
&
0x40
)
tot_len
+=
frag
->
len
-
MP_HEADER_LEN
;
if
(
ippp_table
[
lp
->
ppp_slot
]
->
debug
&
0x40
)
printk
(
KERN_DEBUG
"isdn_mppp: reassembling frames %d "
printk
(
KERN_DEBUG
"isdn_mppp: reassembling frames %d "
"to %d, len %d
\n
"
,
MP_SEQ
(
from
),
"to %d, len %d
\n
"
,
MP_SEQ
(
from
),
lastseq
,
(
MP_SEQ
(
from
)
+
n
-
1
)
&
MP_LONGSEQ_MASK
,
tot_len
);
tot_len
);
if
(
(
skb
=
dev_alloc_skb
(
tot_len
))
==
NULL
)
{
skb
=
dev_alloc_skb
(
tot_len
);
if
(
!
skb
)
printk
(
KERN_ERR
"isdn_mppp: cannot allocate sk buff "
printk
(
KERN_ERR
"isdn_mppp: cannot allocate sk buff "
"of size %d
\n
"
,
tot_len
);
"of size %d
\n
"
,
tot_len
);
isdn_ppp_mp_discard
(
mp
,
from
,
to
);
return
;
found_start
=
0
;
}
skb_queue_walk_safe
(
&
mp
->
frags
,
walk
,
tmp
)
{
if
(
walk
==
from
)
found_start
=
1
;
if
(
!
found_start
)
continue
;
while
(
from
!=
to
)
{
if
(
skb
)
{
unsigned
int
len
=
from
->
len
-
MP_HEADER_LEN
;
unsigned
int
len
=
walk
->
len
-
MP_HEADER_LEN
;
skb_copy_from_linear_data_offset
(
walk
,
MP_HEADER_LEN
,
skb_put
(
skb
,
len
),
len
);
}
__skb_unlink
(
walk
,
&
mp
->
frags
);
isdn_ppp_mp_free_skb
(
mp
,
walk
);
skb_copy_from_linear_data_offset
(
from
,
MP_HEADER_LEN
,
if
(
walk
==
to
)
skb_put
(
skb
,
len
),
break
;
len
);
frag
=
from
->
next
;
isdn_ppp_mp_free_skb
(
mp
,
from
);
from
=
frag
;
}
}
}
}
if
(
!
skb
)
return
;
proto
=
isdn_ppp_strip_proto
(
skb
);
proto
=
isdn_ppp_strip_proto
(
skb
);
isdn_ppp_push_higher
(
net_dev
,
lp
,
skb
,
proto
);
isdn_ppp_push_higher
(
net_dev
,
lp
,
skb
,
proto
);
}
}
static
void
isdn_ppp_mp_free_skb
(
ippp_bundle
*
mp
,
struct
sk_buff
*
skb
)
static
void
isdn_ppp_mp_free_skb
(
ippp_bundle
*
mp
,
struct
sk_buff
*
skb
)
{
{
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb
);
mp
->
frames
--
;
mp
->
frames
--
;
...
...
include/linux/isdn_ppp.h
浏览文件 @
38783e67
...
@@ -157,7 +157,7 @@ typedef struct {
...
@@ -157,7 +157,7 @@ typedef struct {
typedef
struct
{
typedef
struct
{
int
mp_mrru
;
/* unused */
int
mp_mrru
;
/* unused */
struct
sk_buff
*
frags
;
/* fragments sl list -- use skb->nex
t */
struct
sk_buff
_head
frags
;
/* fragments sl lis
t */
long
frames
;
/* number of frames in the frame list */
long
frames
;
/* number of frames in the frame list */
unsigned
int
seq
;
/* last processed packet seq #: any packets
unsigned
int
seq
;
/* last processed packet seq #: any packets
* with smaller seq # will be dropped
* with smaller seq # will be dropped
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录