summaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /net/sched
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/Kconfig508
-rw-r--r--net/sched/Makefile41
-rw-r--r--net/sched/act_api.c894
-rw-r--r--net/sched/cls_api.c642
-rw-r--r--net/sched/cls_basic.c303
-rw-r--r--net/sched/cls_fw.c378
-rw-r--r--net/sched/cls_route.c639
-rw-r--r--net/sched/cls_rsvp.c43
-rw-r--r--net/sched/cls_rsvp.h667
-rw-r--r--net/sched/cls_rsvp6.c44
-rw-r--r--net/sched/cls_tcindex.c537
-rw-r--r--net/sched/cls_u32.c828
-rw-r--r--net/sched/em_cmp.c101
-rw-r--r--net/sched/em_meta.c661
-rw-r--r--net/sched/em_nbyte.c82
-rw-r--r--net/sched/em_u32.c63
-rw-r--r--net/sched/ematch.c524
-rw-r--r--net/sched/estimator.c197
-rw-r--r--net/sched/gact.c231
-rw-r--r--net/sched/ipt.c326
-rw-r--r--net/sched/mirred.c276
-rw-r--r--net/sched/pedit.c288
-rw-r--r--net/sched/police.c612
-rw-r--r--net/sched/sch_api.c1296
-rw-r--r--net/sched/sch_atm.c735
-rw-r--r--net/sched/sch_cbq.c2124
-rw-r--r--net/sched/sch_dsmark.c479
-rw-r--r--net/sched/sch_fifo.c212
-rw-r--r--net/sched/sch_generic.c609
-rw-r--r--net/sched/sch_gred.c630
-rw-r--r--net/sched/sch_hfsc.c1822
-rw-r--r--net/sched/sch_htb.c1759
-rw-r--r--net/sched/sch_ingress.c436
-rw-r--r--net/sched/sch_netem.c598
-rw-r--r--net/sched/sch_prio.c444
-rw-r--r--net/sched/sch_red.c459
-rw-r--r--net/sched/sch_sfq.c497
-rw-r--r--net/sched/sch_tbf.c543
-rw-r--r--net/sched/sch_teql.c511
39 files changed, 22039 insertions, 0 deletions
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
new file mode 100644
index 000000000000..3d1d902dd1a1
--- /dev/null
+++ b/net/sched/Kconfig
@@ -0,0 +1,508 @@
+#
+# Traffic control configuration.
+#
+choice
+ prompt "Packet scheduler clock source"
+ depends on NET_SCHED
+ default NET_SCH_CLK_JIFFIES
+ help
+ Packet schedulers need a monotonic clock that increments at a static
+ rate. The kernel provides several suitable interfaces, each with
+ different properties:
+
+ - high resolution (us or better)
+ - fast to read (minimal locking, no i/o access)
+ - synchronized on all processors
+ - handles cpu clock frequency changes
+
+ but nothing provides all of the above.
+
+config NET_SCH_CLK_JIFFIES
+ bool "Timer interrupt"
+ help
+ Say Y here if you want to use the timer interrupt (jiffies) as clock
+ source. This clock source is fast, synchronized on all processors and
+ handles cpu clock frequency changes, but its resolution is too low
+ for accurate shaping except at very low speed.
+
+config NET_SCH_CLK_GETTIMEOFDAY
+ bool "gettimeofday"
+ help
+ Say Y here if you want to use gettimeofday as clock source. This clock
+ source has high resolution, is synchronized on all processors and
+ handles cpu clock frequency changes, but it is slow.
+
+ Choose this if you need a high resolution clock source but can't use
+ the CPU's cycle counter.
+
+config NET_SCH_CLK_CPU
+ bool "CPU cycle counter"
+ depends on X86_TSC || X86_64 || ALPHA || SPARC64 || PPC64 || IA64
+ help
+ Say Y here if you want to use the CPU's cycle counter as clock source.
+ This is a cheap and high resolution clock source, but on some
+ architectures it is not synchronized on all processors and doesn't
+ handle cpu clock frequency changes.
+
+ The useable cycle counters are:
+
+ x86/x86_64 - Timestamp Counter
+ alpha - Cycle Counter
+ sparc64 - %ticks register
+ ppc64 - Time base
+ ia64 - Interval Time Counter
+
+ Choose this if your CPU's cycle counter is working properly.
+
+endchoice
+
+config NET_SCH_CBQ
+ tristate "CBQ packet scheduler"
+ depends on NET_SCHED
+ ---help---
+ Say Y here if you want to use the Class-Based Queueing (CBQ) packet
+ scheduling algorithm for some of your network devices. This
+ algorithm classifies the waiting packets into a tree-like hierarchy
+ of classes; the leaves of this tree are in turn scheduled by
+ separate algorithms (called "disciplines" in this context).
+
+ See the top of <file:net/sched/sch_cbq.c> for references about the
+ CBQ algorithm.
+
+ CBQ is a commonly used scheduler, so if you're unsure, you should
+ say Y here. Then say Y to all the queueing algorithms below that you
+ want to use as CBQ disciplines. Then say Y to "Packet classifier
+ API" and say Y to all the classifiers you want to use; a classifier
+ is a routine that allows you to sort your outgoing traffic into
+ classes based on a certain criterion.
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_cbq.
+
+config NET_SCH_HTB
+ tristate "HTB packet scheduler"
+ depends on NET_SCHED
+ ---help---
+ Say Y here if you want to use the Hierarchical Token Buckets (HTB)
+ packet scheduling algorithm for some of your network devices. See
+ <http://luxik.cdi.cz/~devik/qos/htb/> for complete manual and
+ in-depth articles.
+
+ HTB is very similar to the CBQ regarding its goals however is has
+ different properties and different algorithm.
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_htb.
+
+config NET_SCH_HFSC
+ tristate "HFSC packet scheduler"
+ depends on NET_SCHED
+ ---help---
+ Say Y here if you want to use the Hierarchical Fair Service Curve
+ (HFSC) packet scheduling algorithm for some of your network devices.
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_hfsc.
+
+#tristate ' H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ
+config NET_SCH_ATM
+ tristate "ATM pseudo-scheduler"
+ depends on NET_SCHED && ATM
+ ---help---
+ Say Y here if you want to use the ATM pseudo-scheduler. This
+ provides a framework for invoking classifiers (aka "filters"), which
+ in turn select classes of this queuing discipline. Each class maps
+ the flow(s) it is handling to a given virtual circuit (see the top of
+ <file:net/sched/sch_atm.c>).
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_atm.
+
+config NET_SCH_PRIO
+ tristate "The simplest PRIO pseudoscheduler"
+ depends on NET_SCHED
+ help
+ Say Y here if you want to use an n-band priority queue packet
+ "scheduler" for some of your network devices or as a leaf discipline
+ for the CBQ scheduling algorithm. If unsure, say Y.
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_prio.
+
+config NET_SCH_RED
+ tristate "RED queue"
+ depends on NET_SCHED
+ help
+ Say Y here if you want to use the Random Early Detection (RED)
+ packet scheduling algorithm for some of your network devices (see
+ the top of <file:net/sched/sch_red.c> for details and references
+ about the algorithm).
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_red.
+
+config NET_SCH_SFQ
+ tristate "SFQ queue"
+ depends on NET_SCHED
+ ---help---
+ Say Y here if you want to use the Stochastic Fairness Queueing (SFQ)
+ packet scheduling algorithm for some of your network devices or as a
+ leaf discipline for the CBQ scheduling algorithm (see the top of
+ <file:net/sched/sch_sfq.c> for details and references about the SFQ
+ algorithm).
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_sfq.
+
+config NET_SCH_TEQL
+ tristate "TEQL queue"
+ depends on NET_SCHED
+ ---help---
+ Say Y here if you want to use the True Link Equalizer (TLE) packet
+ scheduling algorithm for some of your network devices or as a leaf
+ discipline for the CBQ scheduling algorithm. This queueing
+ discipline allows the combination of several physical devices into
+ one virtual device. (see the top of <file:net/sched/sch_teql.c> for
+ details).
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_teql.
+
+config NET_SCH_TBF
+ tristate "TBF queue"
+ depends on NET_SCHED
+ help
+ Say Y here if you want to use the Simple Token Bucket Filter (TBF)
+ packet scheduling algorithm for some of your network devices or as a
+ leaf discipline for the CBQ scheduling algorithm (see the top of
+ <file:net/sched/sch_tbf.c> for a description of the TBF algorithm).
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_tbf.
+
+config NET_SCH_GRED
+ tristate "GRED queue"
+ depends on NET_SCHED
+ help
+ Say Y here if you want to use the Generic Random Early Detection
+ (RED) packet scheduling algorithm for some of your network devices
+ (see the top of <file:net/sched/sch_red.c> for details and
+ references about the algorithm).
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_gred.
+
+config NET_SCH_DSMARK
+ tristate "Diffserv field marker"
+ depends on NET_SCHED
+ help
+ Say Y if you want to schedule packets according to the
+ Differentiated Services architecture proposed in RFC 2475.
+ Technical information on this method, with pointers to associated
+ RFCs, is available at <http://www.gta.ufrj.br/diffserv/>.
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_dsmark.
+
+config NET_SCH_NETEM
+ tristate "Network emulator"
+ depends on NET_SCHED
+ help
+ Say Y if you want to emulate network delay, loss, and packet
+ re-ordering. This is often useful to simulate networks when
+ testing applications or protocols.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sch_netem.
+
+ If unsure, say N.
+
+config NET_SCH_INGRESS
+ tristate "Ingress Qdisc"
+ depends on NET_SCHED
+ help
+ If you say Y here, you will be able to police incoming bandwidth
+ and drop packets when this bandwidth exceeds your desired rate.
+ If unsure, say Y.
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_ingress.
+
+config NET_QOS
+ bool "QoS support"
+ depends on NET_SCHED
+ ---help---
+ Say Y here if you want to include Quality Of Service scheduling
+ features, which means that you will be able to request certain
+ rate-of-flow limits for your network devices.
+
+ This Quality of Service (QoS) support will enable you to use
+ Differentiated Services (diffserv) and Resource Reservation Protocol
+ (RSVP) on your Linux router if you also say Y to "Packet classifier
+ API" and to some classifiers below. Documentation and software is at
+ <http://diffserv.sourceforge.net/>.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about QoS support.
+
+config NET_ESTIMATOR
+ bool "Rate estimator"
+ depends on NET_QOS
+ help
+ In order for Quality of Service scheduling to work, the current
+ rate-of-flow for a network device has to be estimated; if you say Y
+ here, the kernel will do just that.
+
+config NET_CLS
+ bool "Packet classifier API"
+ depends on NET_SCHED
+ ---help---
+ The CBQ scheduling algorithm requires that network packets which are
+ scheduled to be sent out over a network device be classified
+ according to some criterion. If you say Y here, you will get a
+ choice of several different packet classifiers with the following
+ questions.
+
+ This will enable you to use Differentiated Services (diffserv) and
+ Resource Reservation Protocol (RSVP) on your Linux router.
+ Documentation and software is at
+ <http://diffserv.sourceforge.net/>.
+
+config NET_CLS_BASIC
+ tristate "Basic classifier"
+ depends on NET_CLS
+ ---help---
+ Say Y here if you want to be able to classify packets using
+ only extended matches and actions.
+
+ To compile this code as a module, choose M here: the
+ module will be called cls_basic.
+
+config NET_CLS_TCINDEX
+ tristate "TC index classifier"
+ depends on NET_CLS
+ help
+ If you say Y here, you will be able to classify outgoing packets
+ according to the tc_index field of the skb. You will want this
+ feature if you want to implement Differentiated Services using
+ sch_dsmark. If unsure, say Y.
+
+ To compile this code as a module, choose M here: the
+ module will be called cls_tcindex.
+
+config NET_CLS_ROUTE4
+ tristate "Routing table based classifier"
+ depends on NET_CLS
+ select NET_CLS_ROUTE
+ help
+ If you say Y here, you will be able to classify outgoing packets
+ according to the route table entry they matched. If unsure, say Y.
+
+ To compile this code as a module, choose M here: the
+ module will be called cls_route.
+
+config NET_CLS_ROUTE
+ bool
+ default n
+
+config NET_CLS_FW
+ tristate "Firewall based classifier"
+ depends on NET_CLS
+ help
+ If you say Y here, you will be able to classify outgoing packets
+ according to firewall criteria you specified.
+
+ To compile this code as a module, choose M here: the
+ module will be called cls_fw.
+
+config NET_CLS_U32
+ tristate "U32 classifier"
+ depends on NET_CLS
+ help
+ If you say Y here, you will be able to classify outgoing packets
+ according to their destination address. If unsure, say Y.
+
+ To compile this code as a module, choose M here: the
+ module will be called cls_u32.
+
+config CLS_U32_PERF
+ bool "U32 classifier performance counters"
+ depends on NET_CLS_U32
+ help
+ gathers stats that could be used to tune u32 classifier performance.
+ Requires a new iproute2
+ You MUST NOT turn this on if you dont have an update iproute2.
+
+config NET_CLS_IND
+ bool "classify input device (slows things u32/fw) "
+ depends on NET_CLS_U32 || NET_CLS_FW
+ help
+ This option will be killed eventually when a
+ metadata action appears because it slows things a little
+ Available only for u32 and fw classifiers.
+ Requires a new iproute2
+ You MUST NOT turn this on if you dont have an update iproute2.
+
+config CLS_U32_MARK
+ bool "Use nfmark as a key in U32 classifier"
+ depends on NET_CLS_U32 && NETFILTER
+ help
+ This allows you to match mark in a u32 filter.
+ Example:
+ tc filter add dev eth0 protocol ip parent 1:0 prio 5 u32 \
+ match mark 0x0090 0xffff \
+ match ip dst 4.4.4.4 \
+ flowid 1:90
+ You must use a new iproute2 to use this feature.
+
+config NET_CLS_RSVP
+ tristate "Special RSVP classifier"
+ depends on NET_CLS && NET_QOS
+ ---help---
+ The Resource Reservation Protocol (RSVP) permits end systems to
+ request a minimum and maximum data flow rate for a connection; this
+ is important for real time data such as streaming sound or video.
+
+ Say Y here if you want to be able to classify outgoing packets based
+ on their RSVP requests.
+
+ To compile this code as a module, choose M here: the
+ module will be called cls_rsvp.
+
+config NET_CLS_RSVP6
+ tristate "Special RSVP classifier for IPv6"
+ depends on NET_CLS && NET_QOS
+ ---help---
+ The Resource Reservation Protocol (RSVP) permits end systems to
+ request a minimum and maximum data flow rate for a connection; this
+ is important for real time data such as streaming sound or video.
+
+ Say Y here if you want to be able to classify outgoing packets based
+ on their RSVP requests and you are using the new Internet Protocol
+ IPv6 as opposed to the older and more common IPv4.
+
+ To compile this code as a module, choose M here: the
+ module will be called cls_rsvp6.
+
+config NET_EMATCH
+ bool "Extended Matches"
+ depends on NET_CLS
+ ---help---
+ Say Y here if you want to use extended matches on top of classifiers
+ and select the extended matches below.
+
+ Extended matches are small classification helpers not worth writing
+ a separate classifier.
+
+ You must have a recent version of the iproute2 tools in order to use
+ extended matches.
+
+config NET_EMATCH_STACK
+ int "Stack size"
+ depends on NET_EMATCH
+ default "32"
+ ---help---
+ Size of the local stack variable used while evaluating the tree of
+ ematches. Limits the depth of the tree, i.e. the number of
+ encapsulated precedences. Every level requires 4 bytes of addtional
+ stack space.
+
+config NET_EMATCH_CMP
+ tristate "Simple packet data comparison"
+ depends on NET_EMATCH
+ ---help---
+ Say Y here if you want to be able to classify packets based on
+ simple packet data comparisons for 8, 16, and 32bit values.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_cmp.
+
+config NET_EMATCH_NBYTE
+ tristate "Multi byte comparison"
+ depends on NET_EMATCH
+ ---help---
+ Say Y here if you want to be able to classify packets based on
+ multiple byte comparisons mainly useful for IPv6 address comparisons.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_nbyte.
+
+config NET_EMATCH_U32
+ tristate "U32 hashing key"
+ depends on NET_EMATCH
+ ---help---
+ Say Y here if you want to be able to classify packets using
+ the famous u32 key in combination with logic relations.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_u32.
+
+config NET_EMATCH_META
+ tristate "Metadata"
+ depends on NET_EMATCH
+ ---help---
+ Say Y here if you want to be ablt to classify packets based on
+ metadata such as load average, netfilter attributes, socket
+ attributes and routing decisions.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_meta.
+
+config NET_CLS_ACT
+ bool "Packet ACTION"
+ depends on EXPERIMENTAL && NET_CLS && NET_QOS
+ ---help---
+ This option requires you have a new iproute2. It enables
+ tc extensions which can be used with tc classifiers.
+ You MUST NOT turn this on if you dont have an update iproute2.
+
+config NET_ACT_POLICE
+ tristate "Policing Actions"
+ depends on NET_CLS_ACT
+ ---help---
+ If you are using a newer iproute2 select this one, otherwise use one
+ below to select a policer.
+ You MUST NOT turn this on if you dont have an update iproute2.
+
+config NET_ACT_GACT
+ tristate "generic Actions"
+ depends on NET_CLS_ACT
+ ---help---
+ You must have new iproute2 to use this feature.
+ This adds simple filtering actions like drop, accept etc.
+
+config GACT_PROB
+ bool "generic Actions probability"
+ depends on NET_ACT_GACT
+ ---help---
+ Allows generic actions to be randomly or deterministically used.
+
+config NET_ACT_MIRRED
+ tristate "Packet In/Egress redirecton/mirror Actions"
+ depends on NET_CLS_ACT
+ ---help---
+ requires new iproute2
+ This allows packets to be mirrored or redirected to netdevices
+
+config NET_ACT_IPT
+ tristate "iptables Actions"
+ depends on NET_CLS_ACT && NETFILTER && IP_NF_IPTABLES
+ ---help---
+ requires new iproute2
+ This allows iptables targets to be used by tc filters
+
+config NET_ACT_PEDIT
+ tristate "Generic Packet Editor Actions"
+ depends on NET_CLS_ACT
+ ---help---
+ requires new iproute2
+ This allows for packets to be generically edited
+
+config NET_CLS_POLICE
+ bool "Traffic policing (needed for in/egress)"
+ depends on NET_CLS && NET_QOS && NET_CLS_ACT!=y
+ help
+ Say Y to support traffic policing (bandwidth limits). Needed for
+ ingress and egress rate limiting.
+
diff --git a/net/sched/Makefile b/net/sched/Makefile
new file mode 100644
index 000000000000..431e55786efd
--- /dev/null
+++ b/net/sched/Makefile
@@ -0,0 +1,41 @@
+#
+# Makefile for the Linux Traffic Control Unit.
+#
+
+obj-y := sch_generic.o
+
+obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o
+obj-$(CONFIG_NET_CLS) += cls_api.o
+obj-$(CONFIG_NET_CLS_ACT) += act_api.o
+obj-$(CONFIG_NET_ACT_POLICE) += police.o
+obj-$(CONFIG_NET_CLS_POLICE) += police.o
+obj-$(CONFIG_NET_ACT_GACT) += gact.o
+obj-$(CONFIG_NET_ACT_MIRRED) += mirred.o
+obj-$(CONFIG_NET_ACT_IPT) += ipt.o
+obj-$(CONFIG_NET_ACT_PEDIT) += pedit.o
+obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
+obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
+obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o
+obj-$(CONFIG_NET_SCH_HFSC) += sch_hfsc.o
+obj-$(CONFIG_NET_SCH_RED) += sch_red.o
+obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o
+obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
+obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
+obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
+obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
+obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
+obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
+obj-$(CONFIG_NET_SCH_ATM) += sch_atm.o
+obj-$(CONFIG_NET_SCH_NETEM) += sch_netem.o
+obj-$(CONFIG_NET_CLS_U32) += cls_u32.o
+obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o
+obj-$(CONFIG_NET_CLS_FW) += cls_fw.o
+obj-$(CONFIG_NET_CLS_RSVP) += cls_rsvp.o
+obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o
+obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o
+obj-$(CONFIG_NET_CLS_BASIC) += cls_basic.o
+obj-$(CONFIG_NET_EMATCH) += ematch.o
+obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o
+obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
+obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o
+obj-$(CONFIG_NET_EMATCH_META) += em_meta.o
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
new file mode 100644
index 000000000000..5e6cc371b39e
--- /dev/null
+++ b/net/sched/act_api.c
@@ -0,0 +1,894 @@
+/*
+ * net/sched/act_api.c Packet action API.
+ *
+ * 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.
+ *
+ * Author: Jamal Hadi Salim
+ *
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.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/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/init.h>
+#include <linux/kmod.h>
+#include <net/sock.h>
+#include <net/sch_generic.h>
+#include <net/act_api.h>
+
+#if 1 /* control */
+#define DPRINTK(format, args...) printk(KERN_DEBUG format, ##args)
+#else
+#define DPRINTK(format, args...)
+#endif
+#if 0 /* data */
+#define D2PRINTK(format, args...) printk(KERN_DEBUG format, ##args)
+#else
+#define D2PRINTK(format, args...)
+#endif
+
+static struct tc_action_ops *act_base = NULL;
+static DEFINE_RWLOCK(act_mod_lock);
+
+int tcf_register_action(struct tc_action_ops *act)
+{
+ struct tc_action_ops *a, **ap;
+
+ write_lock(&act_mod_lock);
+ for (ap = &act_base; (a = *ap) != NULL; ap = &a->next) {
+ if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
+ write_unlock(&act_mod_lock);
+ return -EEXIST;
+ }
+ }
+ act->next = NULL;
+ *ap = act;
+ write_unlock(&act_mod_lock);
+ return 0;
+}
+
+int tcf_unregister_action(struct tc_action_ops *act)
+{
+ struct tc_action_ops *a, **ap;
+ int err = -ENOENT;
+
+ write_lock(&act_mod_lock);
+ for (ap = &act_base; (a = *ap) != NULL; ap = &a->next)
+ if (a == act)
+ break;
+ if (a) {
+ *ap = a->next;
+ a->next = NULL;
+ err = 0;
+ }
+ write_unlock(&act_mod_lock);
+ return err;
+}
+
+/* lookup by name */
+static struct tc_action_ops *tc_lookup_action_n(char *kind)
+{
+ struct tc_action_ops *a = NULL;
+
+ if (kind) {
+ read_lock(&act_mod_lock);
+ for (a = act_base; a; a = a->next) {
+ if (strcmp(kind, a->kind) == 0) {
+ if (!try_module_get(a->owner)) {
+ read_unlock(&act_mod_lock);
+ return NULL;
+ }
+ break;
+ }
+ }
+ read_unlock(&act_mod_lock);
+ }
+ return a;
+}
+
+/* lookup by rtattr */
+static struct tc_action_ops *tc_lookup_action(struct rtattr *kind)
+{
+ struct tc_action_ops *a = NULL;
+
+ if (kind) {
+ read_lock(&act_mod_lock);
+ for (a = act_base; a; a = a->next) {
+ if (rtattr_strcmp(kind, a->kind) == 0) {
+ if (!try_module_get(a->owner)) {
+ read_unlock(&act_mod_lock);
+ return NULL;
+ }
+ break;
+ }
+ }
+ read_unlock(&act_mod_lock);
+ }
+ return a;
+}
+
+#if 0
+/* lookup by id */
+static struct tc_action_ops *tc_lookup_action_id(u32 type)
+{
+ struct tc_action_ops *a = NULL;
+
+ if (type) {
+ read_lock(&act_mod_lock);
+ for (a = act_base; a; a = a->next) {
+ if (a->type == type) {
+ if (!try_module_get(a->owner)) {
+ read_unlock(&act_mod_lock);
+ return NULL;
+ }
+ break;
+ }
+ }
+ read_unlock(&act_mod_lock);
+ }
+ return a;
+}
+#endif
+
+int tcf_action_exec(struct sk_buff *skb, struct tc_action *act,
+ struct tcf_result *res)
+{
+ struct tc_action *a;
+ int ret = -1;
+
+ if (skb->tc_verd & TC_NCLS) {
+ skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
+ D2PRINTK("(%p)tcf_action_exec: cleared TC_NCLS in %s out %s\n",
+ skb, skb->input_dev ? skb->input_dev->name : "xxx",
+ skb->dev->name);
+ ret = TC_ACT_OK;
+ goto exec_done;
+ }
+ while ((a = act) != NULL) {
+repeat:
+ if (a->ops && a->ops->act) {
+ ret = a->ops->act(&skb, a);
+ if (TC_MUNGED & skb->tc_verd) {
+ /* copied already, allow trampling */
+ skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
+ skb->tc_verd = CLR_TC_MUNGED(skb->tc_verd);
+ }
+ if (ret != TC_ACT_PIPE)
+ goto exec_done;
+ if (ret == TC_ACT_REPEAT)
+ goto repeat; /* we need a ttl - JHS */
+ }
+ act = a->next;
+ }
+exec_done:
+ if (skb->tc_classid > 0) {
+ res->classid = skb->tc_classid;
+ res->class = 0;
+ skb->tc_classid = 0;
+ }
+ return ret;
+}
+
+void tcf_action_destroy(struct tc_action *act, int bind)
+{
+ struct tc_action *a;
+
+ for (a = act; a; a = act) {
+ if (a->ops && a->ops->cleanup) {
+ DPRINTK("tcf_action_destroy destroying %p next %p\n",
+ a, a->next);
+ if (a->ops->cleanup(a, bind) == ACT_P_DELETED)
+ module_put(a->ops->owner);
+ act = act->next;
+ kfree(a);
+ } else { /*FIXME: Remove later - catch insertion bugs*/
+ printk("tcf_action_destroy: BUG? destroying NULL ops\n");
+ act = act->next;
+ kfree(a);
+ }
+ }
+}
+
+int
+tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+ int err = -EINVAL;
+
+ if (a->ops == NULL || a->ops->dump == NULL)
+ return err;
+ return a->ops->dump(skb, a, bind, ref);
+}
+
+int
+tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+ int err = -EINVAL;
+ unsigned char *b = skb->tail;
+ struct rtattr *r;
+
+ if (a->ops == NULL || a->ops->dump == NULL)
+ return err;
+
+ RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
+ if (tcf_action_copy_stats(skb, a, 0))
+ goto rtattr_failure;
+ r = (struct rtattr*) skb->tail;
+ RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ if ((err = tcf_action_dump_old(skb, a, bind, ref)) > 0) {
+ r->rta_len = skb->tail - (u8*)r;
+ return err;
+ }
+
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+int
+tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref)
+{
+ struct tc_action *a;
+ int err = -EINVAL;
+ unsi