2005-04-17 02:20:36 +04:00
# ifndef __NET_PKT_CLS_H
# define __NET_PKT_CLS_H
# include <linux/pkt_cls.h>
# include <net/sch_generic.h>
# include <net/act_api.h>
/* Basic packet classifier frontend definitions. */
2009-11-03 06:26:03 +03:00
struct tcf_walker {
2005-04-17 02:20:36 +04:00
int stop ;
int skip ;
int count ;
int ( * fn ) ( struct tcf_proto * , unsigned long node , struct tcf_walker * ) ;
} ;
2013-07-31 09:47:13 +04:00
int register_tcf_proto_ops ( struct tcf_proto_ops * ops ) ;
int unregister_tcf_proto_ops ( struct tcf_proto_ops * ops ) ;
2005-04-17 02:20:36 +04:00
static inline unsigned long
__cls_set_class ( unsigned long * clp , unsigned long cl )
{
unsigned long old_cl ;
old_cl = * clp ;
* clp = cl ;
return old_cl ;
}
static inline unsigned long
cls_set_class ( struct tcf_proto * tp , unsigned long * clp ,
unsigned long cl )
{
unsigned long old_cl ;
tcf_tree_lock ( tp ) ;
old_cl = __cls_set_class ( clp , cl ) ;
tcf_tree_unlock ( tp ) ;
return old_cl ;
}
static inline void
tcf_bind_filter ( struct tcf_proto * tp , struct tcf_result * r , unsigned long base )
{
unsigned long cl ;
cl = tp - > q - > ops - > cl_ops - > bind_tcf ( tp - > q , base , r - > classid ) ;
cl = cls_set_class ( tp , & r - > class , cl ) ;
if ( cl )
tp - > q - > ops - > cl_ops - > unbind_tcf ( tp - > q , cl ) ;
}
static inline void
tcf_unbind_filter ( struct tcf_proto * tp , struct tcf_result * r )
{
unsigned long cl ;
if ( ( cl = __cls_set_class ( & r - > class , 0 ) ) ! = 0 )
tp - > q - > ops - > cl_ops - > unbind_tcf ( tp - > q , cl ) ;
}
2009-11-03 06:26:03 +03:00
struct tcf_exts {
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_NET_CLS_ACT
2013-12-16 08:15:05 +04:00
__u32 type ; /* for backward compat(TCA_OLD_COMPAT) */
struct list_head actions ;
2005-04-17 02:20:36 +04:00
# endif
2013-12-16 08:15:07 +04:00
/* Map to export classifier specific extension TLV types to the
* generic extensions API . Unsupported extensions must be set to 0.
*/
2005-04-17 02:20:36 +04:00
int action ;
int police ;
} ;
2013-12-16 08:15:07 +04:00
static inline void tcf_exts_init ( struct tcf_exts * exts , int action , int police )
2013-12-16 08:15:05 +04:00
{
# ifdef CONFIG_NET_CLS_ACT
2013-12-16 08:15:07 +04:00
exts - > type = 0 ;
2013-12-16 08:15:05 +04:00
INIT_LIST_HEAD ( & exts - > actions ) ;
# endif
2013-12-16 08:15:07 +04:00
exts - > action = action ;
exts - > police = police ;
2013-12-16 08:15:05 +04:00
}
2005-04-17 02:20:36 +04:00
/**
* tcf_exts_is_predicative - check if a predicative extension is present
* @ exts : tc filter extensions handle
*
* Returns 1 if a predicative extension is present , i . e . an extension which
* might cause further actions and thus overrule the regular tcf_result .
*/
static inline int
tcf_exts_is_predicative ( struct tcf_exts * exts )
{
# ifdef CONFIG_NET_CLS_ACT
2013-12-16 08:15:05 +04:00
return ! list_empty ( & exts - > actions ) ;
2005-04-17 02:20:36 +04:00
# else
return 0 ;
# endif
}
/**
* tcf_exts_is_available - check if at least one extension is present
* @ exts : tc filter extensions handle
*
* Returns 1 if at least one extension is present .
*/
static inline int
tcf_exts_is_available ( struct tcf_exts * exts )
{
/* All non-predicative extensions must be added here. */
return tcf_exts_is_predicative ( exts ) ;
}
/**
* tcf_exts_exec - execute tc filter extensions
* @ skb : socket buffer
* @ exts : tc filter extensions handle
* @ res : desired result
*
* Executes all configured extensions . Returns 0 on a normal execution ,
* a negative number if the filter must be considered unmatched or
* a positive action code ( TC_ACT_ * ) which must be returned to the
* underlying layer .
*/
static inline int
tcf_exts_exec ( struct sk_buff * skb , struct tcf_exts * exts ,
struct tcf_result * res )
{
# ifdef CONFIG_NET_CLS_ACT
2013-12-16 08:15:05 +04:00
if ( ! list_empty ( & exts - > actions ) )
return tcf_action_exec ( skb , & exts - > actions , res ) ;
2005-04-17 02:20:36 +04:00
# endif
return 0 ;
}
2013-07-31 09:47:13 +04:00
int tcf_exts_validate ( struct net * net , struct tcf_proto * tp ,
struct nlattr * * tb , struct nlattr * rate_tlv ,
2014-04-26 00:54:06 +04:00
struct tcf_exts * exts , bool ovr ) ;
2013-07-31 09:47:13 +04:00
void tcf_exts_destroy ( struct tcf_proto * tp , struct tcf_exts * exts ) ;
void tcf_exts_change ( struct tcf_proto * tp , struct tcf_exts * dst ,
struct tcf_exts * src ) ;
2013-12-16 08:15:07 +04:00
int tcf_exts_dump ( struct sk_buff * skb , struct tcf_exts * exts ) ;
int tcf_exts_dump_stats ( struct sk_buff * skb , struct tcf_exts * exts ) ;
2005-04-17 02:20:36 +04:00
/**
* struct tcf_pkt_info - packet information
*/
2009-11-03 06:26:03 +03:00
struct tcf_pkt_info {
2005-04-17 02:20:36 +04:00
unsigned char * ptr ;
int nexthdr ;
} ;
# ifdef CONFIG_NET_EMATCH
struct tcf_ematch_ops ;
/**
* struct tcf_ematch - extended match ( ematch )
*
* @ matchid : identifier to allow userspace to reidentify a match
* @ flags : flags specifying attributes and the relation to other matches
* @ ops : the operations lookup table of the corresponding ematch module
* @ datalen : length of the ematch specific configuration data
* @ data : ematch specific data
*/
2009-11-03 06:26:03 +03:00
struct tcf_ematch {
2005-04-17 02:20:36 +04:00
struct tcf_ematch_ops * ops ;
unsigned long data ;
unsigned int datalen ;
u16 matchid ;
u16 flags ;
} ;
static inline int tcf_em_is_container ( struct tcf_ematch * em )
{
return ! em - > ops ;
}
static inline int tcf_em_is_simple ( struct tcf_ematch * em )
{
return em - > flags & TCF_EM_SIMPLE ;
}
static inline int tcf_em_is_inverted ( struct tcf_ematch * em )
{
return em - > flags & TCF_EM_INVERT ;
}
static inline int tcf_em_last_match ( struct tcf_ematch * em )
{
return ( em - > flags & TCF_EM_REL_MASK ) = = TCF_EM_REL_END ;
}
static inline int tcf_em_early_end ( struct tcf_ematch * em , int result )
{
if ( tcf_em_last_match ( em ) )
return 1 ;
if ( result = = 0 & & em - > flags & TCF_EM_REL_AND )
return 1 ;
if ( result ! = 0 & & em - > flags & TCF_EM_REL_OR )
return 1 ;
return 0 ;
}
/**
* struct tcf_ematch_tree - ematch tree handle
*
* @ hdr : ematch tree header supplied by userspace
* @ matches : array of ematches
*/
2009-11-03 06:26:03 +03:00
struct tcf_ematch_tree {
2005-04-17 02:20:36 +04:00
struct tcf_ematch_tree_hdr hdr ;
struct tcf_ematch * matches ;
} ;
/**
* struct tcf_ematch_ops - ematch module operations
*
* @ kind : identifier ( kind ) of this ematch module
* @ datalen : length of expected configuration data ( optional )
* @ change : called during validation ( optional )
* @ match : called during ematch tree evaluation , must return 1 / 0
* @ destroy : called during destroyage ( optional )
* @ dump : called during dumping process ( optional )
* @ owner : owner , must be set to THIS_MODULE
* @ link : link to previous / next ematch module ( internal use )
*/
2009-11-03 06:26:03 +03:00
struct tcf_ematch_ops {
2005-04-17 02:20:36 +04:00
int kind ;
int datalen ;
int ( * change ) ( struct tcf_proto * , void * ,
int , struct tcf_ematch * ) ;
int ( * match ) ( struct sk_buff * , struct tcf_ematch * ,
struct tcf_pkt_info * ) ;
void ( * destroy ) ( struct tcf_proto * ,
struct tcf_ematch * ) ;
int ( * dump ) ( struct sk_buff * , struct tcf_ematch * ) ;
struct module * owner ;
struct list_head link ;
} ;
2013-07-31 09:47:13 +04:00
int tcf_em_register ( struct tcf_ematch_ops * ) ;
void tcf_em_unregister ( struct tcf_ematch_ops * ) ;
int tcf_em_tree_validate ( struct tcf_proto * , struct nlattr * ,
struct tcf_ematch_tree * ) ;
void tcf_em_tree_destroy ( struct tcf_proto * , struct tcf_ematch_tree * ) ;
int tcf_em_tree_dump ( struct sk_buff * , struct tcf_ematch_tree * , int ) ;
int __tcf_em_tree_match ( struct sk_buff * , struct tcf_ematch_tree * ,
struct tcf_pkt_info * ) ;
2005-04-17 02:20:36 +04:00
/**
* tcf_em_tree_change - replace ematch tree of a running classifier
*
* @ tp : classifier kind handle
* @ dst : destination ematch tree variable
* @ src : source ematch tree ( temporary tree from tcf_em_tree_validate )
*
* This functions replaces the ematch tree in @ dst with the ematch
* tree in @ src . The classifier in charge of the ematch tree may be
* running .
*/
static inline void tcf_em_tree_change ( struct tcf_proto * tp ,
struct tcf_ematch_tree * dst ,
struct tcf_ematch_tree * src )
{
tcf_tree_lock ( tp ) ;
memcpy ( dst , src , sizeof ( * dst ) ) ;
tcf_tree_unlock ( tp ) ;
}
/**
* tcf_em_tree_match - evaulate an ematch tree
*
* @ skb : socket buffer of the packet in question
* @ tree : ematch tree to be used for evaluation
* @ info : packet information examined by classifier
*
* This function matches @ skb against the ematch tree in @ tree by going
* through all ematches respecting their logic relations returning
* as soon as the result is obvious .
*
* Returns 1 if the ematch tree as - one matches , no ematches are configured
* or ematch is not enabled in the kernel , otherwise 0 is returned .
*/
static inline int tcf_em_tree_match ( struct sk_buff * skb ,
struct tcf_ematch_tree * tree ,
struct tcf_pkt_info * info )
{
if ( tree - > hdr . nmatches )
return __tcf_em_tree_match ( skb , tree , info ) ;
else
return 1 ;
}
2007-07-12 06:46:26 +04:00
# define MODULE_ALIAS_TCF_EMATCH(kind) MODULE_ALIAS("ematch-kind-" __stringify(kind))
2005-04-17 02:20:36 +04:00
# else /* CONFIG_NET_EMATCH */
2009-11-03 06:26:03 +03:00
struct tcf_ematch_tree {
2005-04-17 02:20:36 +04:00
} ;
# define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0)
# define tcf_em_tree_destroy(tp, t) do { (void)(t); } while(0)
# define tcf_em_tree_dump(skb, t, tlv) (0)
# define tcf_em_tree_change(tp, dst, src) do { } while(0)
# define tcf_em_tree_match(skb, t, info) ((void)(info), 1)
# endif /* CONFIG_NET_EMATCH */
static inline unsigned char * tcf_get_base_ptr ( struct sk_buff * skb , int layer )
{
switch ( layer ) {
case TCF_LAYER_LINK :
return skb - > data ;
case TCF_LAYER_NETWORK :
2007-04-11 07:50:43 +04:00
return skb_network_header ( skb ) ;
2005-04-17 02:20:36 +04:00
case TCF_LAYER_TRANSPORT :
2007-04-26 05:04:18 +04:00
return skb_transport_header ( skb ) ;
2005-04-17 02:20:36 +04:00
}
return NULL ;
}
2007-04-21 09:47:35 +04:00
static inline int tcf_valid_offset ( const struct sk_buff * skb ,
const unsigned char * ptr , const int len )
2005-04-17 02:20:36 +04:00
{
2010-12-21 23:43:16 +03:00
return likely ( ( ptr + len ) < = skb_tail_pointer ( skb ) & &
ptr > = skb - > head & &
( ptr < = ( ptr + len ) ) ) ;
2005-04-17 02:20:36 +04:00
}
# ifdef CONFIG_NET_CLS_IND
2007-12-04 12:15:45 +03:00
# include <net/net_namespace.h>
2005-04-17 02:20:36 +04:00
static inline int
2014-01-10 04:14:02 +04:00
tcf_change_indev ( struct net * net , struct nlattr * indev_tlv )
2005-04-17 02:20:36 +04:00
{
2014-01-10 04:14:02 +04:00
char indev [ IFNAMSIZ ] ;
struct net_device * dev ;
2008-01-23 09:11:33 +03:00
if ( nla_strlcpy ( indev , indev_tlv , IFNAMSIZ ) > = IFNAMSIZ )
2005-04-17 02:20:36 +04:00
return - EINVAL ;
2014-01-10 04:14:02 +04:00
dev = __dev_get_by_name ( net , indev ) ;
if ( ! dev )
return - ENODEV ;
return dev - > ifindex ;
2005-04-17 02:20:36 +04:00
}
2014-01-10 04:14:02 +04:00
static inline bool
tcf_match_indev ( struct sk_buff * skb , int ifindex )
2005-04-17 02:20:36 +04:00
{
2014-01-10 04:14:02 +04:00
if ( ! ifindex )
return true ;
if ( ! skb - > skb_iif )
return false ;
return ifindex = = skb - > skb_iif ;
2005-04-17 02:20:36 +04:00
}
# endif /* CONFIG_NET_CLS_IND */
# endif