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
Kirill Smelkov
linux
Commits
19c7c61c
Commit
19c7c61c
authored
Mar 18, 2004
by
Stephen Hemminger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[NET_SCHED]: Add packet delay scheduler.
parent
096acddf
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
287 additions
and
0 deletions
+287
-0
include/linux/pkt_sched.h
include/linux/pkt_sched.h
+6
-0
net/sched/Kconfig
net/sched/Kconfig
+11
-0
net/sched/Makefile
net/sched/Makefile
+1
-0
net/sched/sch_delay.c
net/sched/sch_delay.c
+269
-0
No files found.
include/linux/pkt_sched.h
View file @
19c7c61c
...
@@ -432,4 +432,10 @@ enum {
...
@@ -432,4 +432,10 @@ enum {
#define TCA_ATM_MAX TCA_ATM_STATE
#define TCA_ATM_MAX TCA_ATM_STATE
/* Delay section */
struct
tc_dly_qopt
{
__u32
latency
;
__u32
limit
;
};
#endif
#endif
net/sched/Kconfig
View file @
19c7c61c
...
@@ -164,6 +164,17 @@ config NET_SCH_DSMARK
...
@@ -164,6 +164,17 @@ config NET_SCH_DSMARK
To compile this code as a module, choose M here: the
To compile this code as a module, choose M here: the
module will be called sch_dsmark.
module will be called sch_dsmark.
config NET_SCH_DELAY
tristate "Delay simulator"
depends on NET_SCHED
help
Say Y if you want to delay packets by a fixed amount of
time. This is often useful to simulate network delay when
testing applications or protocols.
To compile this driver as a module, choose M here: the module
will be called sch_delay.
config NET_SCH_INGRESS
config NET_SCH_INGRESS
tristate "Ingress Qdisc"
tristate "Ingress Qdisc"
depends on NET_SCHED && NETFILTER
depends on NET_SCHED && NETFILTER
...
...
net/sched/Makefile
View file @
19c7c61c
...
@@ -22,6 +22,7 @@ obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
...
@@ -22,6 +22,7 @@ obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
obj-$(CONFIG_NET_SCH_TEQL)
+=
sch_teql.o
obj-$(CONFIG_NET_SCH_TEQL)
+=
sch_teql.o
obj-$(CONFIG_NET_SCH_PRIO)
+=
sch_prio.o
obj-$(CONFIG_NET_SCH_PRIO)
+=
sch_prio.o
obj-$(CONFIG_NET_SCH_ATM)
+=
sch_atm.o
obj-$(CONFIG_NET_SCH_ATM)
+=
sch_atm.o
obj-$(CONFIG_NET_SCH_DELAY)
+=
sch_delay.o
obj-$(CONFIG_NET_CLS_U32)
+=
cls_u32.o
obj-$(CONFIG_NET_CLS_U32)
+=
cls_u32.o
obj-$(CONFIG_NET_CLS_ROUTE4)
+=
cls_route.o
obj-$(CONFIG_NET_CLS_ROUTE4)
+=
cls_route.o
obj-$(CONFIG_NET_CLS_FW)
+=
cls_fw.o
obj-$(CONFIG_NET_CLS_FW)
+=
cls_fw.o
...
...
net/sched/sch_delay.c
0 → 100644
View file @
19c7c61c
/*
* net/sched/sch_delay.c Simple constant delay
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Authors: Stephen Hemminger <shemminger@osdl.org>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/notifier.h>
#include <net/ip.h>
#include <net/route.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/pkt_sched.h>
/* Network delay simulator
This scheduler adds a fixed delay to all packets.
Similar to NISTnet and BSD Dummynet.
It uses byte fifo underneath similar to TBF */
struct
dly_sched_data
{
u32
latency
;
u32
limit
;
struct
timer_list
timer
;
struct
Qdisc
*
qdisc
;
};
/* Time stamp put into socket buffer control block */
struct
dly_skb_cb
{
psched_time_t
queuetime
;
};
/* Enqueue packets with underlying discipline (fifo)
* but mark them with current time first.
*/
static
int
dly_enqueue
(
struct
sk_buff
*
skb
,
struct
Qdisc
*
sch
)
{
struct
dly_sched_data
*
q
=
(
struct
dly_sched_data
*
)
sch
->
data
;
struct
dly_skb_cb
*
cb
=
(
struct
dly_skb_cb
*
)
skb
->
cb
;
int
ret
;
PSCHED_GET_TIME
(
cb
->
queuetime
);
/* Queue to underlying scheduler */
ret
=
q
->
qdisc
->
enqueue
(
skb
,
q
->
qdisc
);
if
(
ret
)
sch
->
stats
.
drops
++
;
else
{
sch
->
q
.
qlen
++
;
sch
->
stats
.
bytes
+=
skb
->
len
;
sch
->
stats
.
packets
++
;
}
return
0
;
}
/* Requeue packets but don't change time stamp */
static
int
dly_requeue
(
struct
sk_buff
*
skb
,
struct
Qdisc
*
sch
)
{
struct
dly_sched_data
*
q
=
(
struct
dly_sched_data
*
)
sch
->
data
;
int
ret
;
ret
=
q
->
qdisc
->
ops
->
requeue
(
skb
,
q
->
qdisc
);
if
(
ret
==
0
)
sch
->
q
.
qlen
++
;
return
ret
;
}
static
unsigned
int
dly_drop
(
struct
Qdisc
*
sch
)
{
struct
dly_sched_data
*
q
=
(
struct
dly_sched_data
*
)
sch
->
data
;
unsigned
int
len
;
len
=
q
->
qdisc
->
ops
->
drop
(
q
->
qdisc
);
if
(
len
)
{
sch
->
q
.
qlen
--
;
sch
->
stats
.
drops
++
;
}
return
len
;
}
/* Dequeue packet.
* If packet needs to be held up, then stop the
* queue and set timer to wakeup later.
*/
static
struct
sk_buff
*
dly_dequeue
(
struct
Qdisc
*
sch
)
{
struct
dly_sched_data
*
q
=
(
struct
dly_sched_data
*
)
sch
->
data
;
struct
sk_buff
*
skb
=
q
->
qdisc
->
dequeue
(
q
->
qdisc
);
if
(
skb
)
{
struct
dly_skb_cb
*
cb
=
(
struct
dly_skb_cb
*
)
skb
->
cb
;
psched_time_t
now
;
long
diff
;
PSCHED_GET_TIME
(
now
);
diff
=
q
->
latency
-
PSCHED_TDIFF
(
now
,
cb
->
queuetime
);
if
(
diff
<=
0
)
{
sch
->
q
.
qlen
--
;
sch
->
flags
&=
~
TCQ_F_THROTTLED
;
return
skb
;
}
if
(
!
netif_queue_stopped
(
sch
->
dev
))
{
long
delay
=
PSCHED_US2JIFFIE
(
diff
);
if
(
delay
<=
0
)
delay
=
1
;
mod_timer
(
&
q
->
timer
,
jiffies
+
delay
);
}
if
(
q
->
qdisc
->
ops
->
requeue
(
skb
,
q
->
qdisc
)
!=
NET_XMIT_SUCCESS
)
{
sch
->
q
.
qlen
--
;
sch
->
stats
.
drops
++
;
}
sch
->
flags
|=
TCQ_F_THROTTLED
;
}
return
NULL
;
}
static
void
dly_reset
(
struct
Qdisc
*
sch
)
{
struct
dly_sched_data
*
q
=
(
struct
dly_sched_data
*
)
sch
->
data
;
qdisc_reset
(
q
->
qdisc
);
sch
->
q
.
qlen
=
0
;
sch
->
flags
&=
~
TCQ_F_THROTTLED
;
del_timer
(
&
q
->
timer
);
}
static
void
dly_timer
(
unsigned
long
arg
)
{
struct
Qdisc
*
sch
=
(
struct
Qdisc
*
)
arg
;
sch
->
flags
&=
~
TCQ_F_THROTTLED
;
netif_schedule
(
sch
->
dev
);
}
/* Tell Fifo the new limit. */
static
int
change_limit
(
struct
Qdisc
*
q
,
u32
limit
)
{
struct
rtattr
*
rta
;
int
ret
;
rta
=
kmalloc
(
RTA_LENGTH
(
sizeof
(
struct
tc_fifo_qopt
)),
GFP_KERNEL
);
if
(
!
rta
)
return
-
ENOMEM
;
rta
->
rta_type
=
RTM_NEWQDISC
;
((
struct
tc_fifo_qopt
*
)
RTA_DATA
(
rta
))
->
limit
=
limit
;
ret
=
q
->
ops
->
change
(
q
,
rta
);
kfree
(
rta
);
return
ret
;
}
/* Setup underlying FIFO discipline */
static
int
dly_change
(
struct
Qdisc
*
sch
,
struct
rtattr
*
opt
)
{
struct
dly_sched_data
*
q
=
(
struct
dly_sched_data
*
)
sch
->
data
;
struct
tc_dly_qopt
*
qopt
=
RTA_DATA
(
opt
);
int
err
;
if
(
q
->
qdisc
==
&
noop_qdisc
)
{
struct
Qdisc
*
child
=
qdisc_create_dflt
(
sch
->
dev
,
&
bfifo_qdisc_ops
);
if
(
!
child
)
return
-
EINVAL
;
q
->
qdisc
=
child
;
}
err
=
change_limit
(
q
->
qdisc
,
qopt
->
limit
);
if
(
err
)
{
qdisc_destroy
(
q
->
qdisc
);
q
->
qdisc
=
&
noop_qdisc
;
}
else
{
q
->
latency
=
qopt
->
latency
;
q
->
limit
=
qopt
->
limit
;
}
return
err
;
}
static
int
dly_init
(
struct
Qdisc
*
sch
,
struct
rtattr
*
opt
)
{
struct
dly_sched_data
*
q
=
(
struct
dly_sched_data
*
)
sch
->
data
;
if
(
!
opt
)
return
-
EINVAL
;
init_timer
(
&
q
->
timer
);
q
->
timer
.
function
=
dly_timer
;
q
->
timer
.
data
=
(
unsigned
long
)
sch
;
q
->
qdisc
=
&
noop_qdisc
;
return
dly_change
(
sch
,
opt
);
}
static
void
dly_destroy
(
struct
Qdisc
*
sch
)
{
struct
dly_sched_data
*
q
=
(
struct
dly_sched_data
*
)
sch
->
data
;
del_timer
(
&
q
->
timer
);
qdisc_destroy
(
q
->
qdisc
);
q
->
qdisc
=
&
noop_qdisc
;
}
static
int
dly_dump
(
struct
Qdisc
*
sch
,
struct
sk_buff
*
skb
)
{
struct
dly_sched_data
*
q
=
(
struct
dly_sched_data
*
)
sch
->
data
;
unsigned
char
*
b
=
skb
->
tail
;
struct
tc_dly_qopt
qopt
;
qopt
.
latency
=
q
->
latency
;
qopt
.
limit
=
q
->
limit
;
RTA_PUT
(
skb
,
TCA_OPTIONS
,
sizeof
(
qopt
),
&
qopt
);
return
skb
->
len
;
rtattr_failure:
skb_trim
(
skb
,
b
-
skb
->
data
);
return
-
1
;
}
static
struct
Qdisc_ops
dly_qdisc_ops
=
{
.
id
=
"delay"
,
.
priv_size
=
sizeof
(
struct
dly_sched_data
),
.
enqueue
=
dly_enqueue
,
.
dequeue
=
dly_dequeue
,
.
requeue
=
dly_requeue
,
.
drop
=
dly_drop
,
.
init
=
dly_init
,
.
reset
=
dly_reset
,
.
destroy
=
dly_destroy
,
.
change
=
dly_change
,
.
dump
=
dly_dump
,
.
owner
=
THIS_MODULE
,
};
static
int
__init
dly_module_init
(
void
)
{
return
register_qdisc
(
&
dly_qdisc_ops
);
}
static
void
__exit
dly_module_exit
(
void
)
{
unregister_qdisc
(
&
dly_qdisc_ops
);
}
module_init
(
dly_module_init
)
module_exit
(
dly_module_exit
)
MODULE_LICENSE
(
"GPL"
);
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