2007-02-09 17:25:16 +03:00
/* net/sched/sch_ingress.c - Ingress qdisc
2005-04-17 02:20:36 +04:00
* 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 : Jamal Hadi Salim 1999
*/
# include <linux/module.h>
# include <linux/types.h>
2007-07-03 09:49:07 +04:00
# include <linux/list.h>
2005-04-17 02:20:36 +04:00
# include <linux/skbuff.h>
# include <linux/rtnetlink.h>
2007-03-26 10:06:12 +04:00
# include <net/netlink.h>
2005-04-17 02:20:36 +04:00
# include <net/pkt_sched.h>
struct ingress_qdisc_data {
2014-09-13 07:05:27 +04:00
struct tcf_proto __rcu * filter_list ;
2005-04-17 02:20:36 +04:00
} ;
/* ------------------------- Class/flow operations ------------------------- */
static struct Qdisc * ingress_leaf ( struct Qdisc * sch , unsigned long arg )
{
return NULL ;
}
2008-01-21 11:11:01 +03:00
static unsigned long ingress_get ( struct Qdisc * sch , u32 classid )
2005-04-17 02:20:36 +04:00
{
return TC_H_MIN ( classid ) + 1 ;
}
static unsigned long ingress_bind_filter ( struct Qdisc * sch ,
2008-01-21 11:11:01 +03:00
unsigned long parent , u32 classid )
2005-04-17 02:20:36 +04:00
{
return ingress_get ( sch , classid ) ;
}
static void ingress_put ( struct Qdisc * sch , unsigned long cl )
{
}
2008-01-21 11:11:01 +03:00
static void ingress_walk ( struct Qdisc * sch , struct qdisc_walker * walker )
2005-04-17 02:20:36 +04:00
{
}
2014-09-13 07:05:27 +04:00
static struct tcf_proto __rcu * * ingress_find_tcf ( struct Qdisc * sch ,
unsigned long cl )
2005-04-17 02:20:36 +04:00
{
2008-01-21 11:11:48 +03:00
struct ingress_qdisc_data * p = qdisc_priv ( sch ) ;
2005-04-17 02:20:36 +04:00
return & p - > filter_list ;
}
/* --------------------------- Qdisc operations ---------------------------- */
2008-01-21 11:11:01 +03:00
static int ingress_enqueue ( struct sk_buff * skb , struct Qdisc * sch )
2005-04-17 02:20:36 +04:00
{
2008-01-21 11:11:48 +03:00
struct ingress_qdisc_data * p = qdisc_priv ( sch ) ;
2005-04-17 02:20:36 +04:00
struct tcf_result res ;
2014-09-13 07:05:27 +04:00
struct tcf_proto * fl = rcu_dereference_bh ( p - > filter_list ) ;
2005-04-17 02:20:36 +04:00
int result ;
2014-09-13 07:05:27 +04:00
result = tc_classify ( skb , fl , & res ) ;
2008-01-21 11:11:21 +03:00
2011-01-09 11:30:54 +03:00
qdisc_bstats_update ( sch , skb ) ;
2005-04-17 02:20:36 +04:00
switch ( result ) {
2008-01-21 11:11:01 +03:00
case TC_ACT_SHOT :
result = TC_ACT_SHOT ;
sch - > qstats . drops + + ;
break ;
case TC_ACT_STOLEN :
case TC_ACT_QUEUED :
result = TC_ACT_STOLEN ;
break ;
case TC_ACT_RECLASSIFY :
case TC_ACT_OK :
skb - > tc_index = TC_H_MIN ( res . classid ) ;
default :
result = TC_ACT_OK ;
break ;
2007-04-21 04:09:22 +04:00
}
2005-04-17 02:20:36 +04:00
return result ;
}
/* ------------------------------------------------------------- */
static void ingress_destroy ( struct Qdisc * sch )
{
2008-01-21 11:11:48 +03:00
struct ingress_qdisc_data * p = qdisc_priv ( sch ) ;
2005-04-17 02:20:36 +04:00
2008-07-02 06:52:38 +04:00
tcf_destroy_chain ( & p - > filter_list ) ;
2005-04-17 02:20:36 +04:00
}
static int ingress_dump ( struct Qdisc * sch , struct sk_buff * skb )
{
2008-01-24 07:34:11 +03:00
struct nlattr * nest ;
2005-04-17 02:20:36 +04:00
2008-01-24 07:34:11 +03:00
nest = nla_nest_start ( skb , TCA_OPTIONS ) ;
if ( nest = = NULL )
goto nla_put_failure ;
2014-03-12 06:20:32 +04:00
return nla_nest_end ( skb , nest ) ;
2005-04-17 02:20:36 +04:00
2008-01-23 09:11:17 +03:00
nla_put_failure :
2008-01-24 07:34:11 +03:00
nla_nest_cancel ( skb , nest ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
2007-11-14 12:44:41 +03:00
static const struct Qdisc_class_ops ingress_class_ops = {
2005-04-17 02:20:36 +04:00
. leaf = ingress_leaf ,
. get = ingress_get ,
. put = ingress_put ,
. walk = ingress_walk ,
. tcf_chain = ingress_find_tcf ,
. bind_tcf = ingress_bind_filter ,
. unbind_tcf = ingress_put ,
} ;
2007-11-14 12:44:41 +03:00
static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
2005-04-17 02:20:36 +04:00
. cl_ops = & ingress_class_ops ,
. id = " ingress " ,
. priv_size = sizeof ( struct ingress_qdisc_data ) ,
. enqueue = ingress_enqueue ,
. destroy = ingress_destroy ,
. dump = ingress_dump ,
. owner = THIS_MODULE ,
} ;
static int __init ingress_module_init ( void )
{
2008-01-21 11:14:05 +03:00
return register_qdisc ( & ingress_qdisc_ops ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-21 11:11:01 +03:00
2007-02-09 17:25:16 +03:00
static void __exit ingress_module_exit ( void )
2005-04-17 02:20:36 +04:00
{
unregister_qdisc ( & ingress_qdisc_ops ) ;
}
2008-01-21 11:11:01 +03:00
2005-04-17 02:20:36 +04:00
module_init ( ingress_module_init )
module_exit ( ingress_module_exit )
MODULE_LICENSE ( " GPL " ) ;