2005-04-25 07:10:16 +04:00
/*
* include / net / act_generic . h
*
*/
2005-05-19 23:42:39 +04:00
# ifndef _NET_ACT_GENERIC_H
# define _NET_ACT_GENERIC_H
2005-04-25 07:10:16 +04:00
static inline int tcf_defact_release ( struct tcf_defact * p , int bind )
{
int ret = 0 ;
if ( p ) {
if ( bind ) {
p - > bindcnt - - ;
}
p - > refcnt - - ;
if ( p - > bindcnt < = 0 & & p - > refcnt < = 0 ) {
kfree ( p - > defdata ) ;
tcf_hash_destroy ( p ) ;
ret = 1 ;
}
}
return ret ;
}
static inline int
alloc_defdata ( struct tcf_defact * p , u32 datalen , void * defdata )
{
p - > defdata = kmalloc ( datalen , GFP_KERNEL ) ;
if ( p - > defdata = = NULL )
return - ENOMEM ;
p - > datalen = datalen ;
memcpy ( p - > defdata , defdata , datalen ) ;
return 0 ;
}
static inline int
realloc_defdata ( struct tcf_defact * p , u32 datalen , void * defdata )
{
/* safer to be just brute force for now */
kfree ( p - > defdata ) ;
return alloc_defdata ( p , datalen , defdata ) ;
}
static inline int
tcf_defact_init ( struct rtattr * rta , struct rtattr * est ,
struct tc_action * a , int ovr , int bind )
{
struct rtattr * tb [ TCA_DEF_MAX ] ;
struct tc_defact * parm ;
struct tcf_defact * p ;
void * defdata ;
u32 datalen = 0 ;
int ret = 0 ;
if ( rta = = NULL | | rtattr_parse_nested ( tb , TCA_DEF_MAX , rta ) < 0 )
return - EINVAL ;
if ( tb [ TCA_DEF_PARMS - 1 ] = = NULL | |
RTA_PAYLOAD ( tb [ TCA_DEF_PARMS - 1 ] ) < sizeof ( * parm ) )
return - EINVAL ;
parm = RTA_DATA ( tb [ TCA_DEF_PARMS - 1 ] ) ;
defdata = RTA_DATA ( tb [ TCA_DEF_DATA - 1 ] ) ;
if ( defdata = = NULL )
return - EINVAL ;
datalen = RTA_PAYLOAD ( tb [ TCA_DEF_DATA - 1 ] ) ;
if ( datalen < = 0 )
return - EINVAL ;
p = tcf_hash_check ( parm - > index , a , ovr , bind ) ;
if ( p = = NULL ) {
p = tcf_hash_create ( parm - > index , est , a , sizeof ( * p ) , ovr , bind ) ;
if ( p = = NULL )
return - ENOMEM ;
ret = alloc_defdata ( p , datalen , defdata ) ;
if ( ret < 0 ) {
kfree ( p ) ;
return ret ;
}
ret = ACT_P_CREATED ;
} else {
if ( ! ovr ) {
tcf_defact_release ( p , bind ) ;
return - EEXIST ;
}
realloc_defdata ( p , datalen , defdata ) ;
}
spin_lock_bh ( & p - > lock ) ;
p - > action = parm - > action ;
spin_unlock_bh ( & p - > lock ) ;
if ( ret = = ACT_P_CREATED )
tcf_hash_insert ( p ) ;
return ret ;
}
static inline int tcf_defact_cleanup ( struct tc_action * a , int bind )
{
struct tcf_defact * p = PRIV ( a , defact ) ;
if ( p ! = NULL )
return tcf_defact_release ( p , bind ) ;
return 0 ;
}
static inline int
tcf_defact_dump ( struct sk_buff * skb , struct tc_action * a , int bind , int ref )
{
unsigned char * b = skb - > tail ;
struct tc_defact opt ;
struct tcf_defact * p = PRIV ( a , defact ) ;
struct tcf_t t ;
opt . index = p - > index ;
opt . refcnt = p - > refcnt - ref ;
opt . bindcnt = p - > bindcnt - bind ;
opt . action = p - > action ;
RTA_PUT ( skb , TCA_DEF_PARMS , sizeof ( opt ) , & opt ) ;
RTA_PUT ( skb , TCA_DEF_DATA , p - > datalen , p - > defdata ) ;
t . install = jiffies_to_clock_t ( jiffies - p - > tm . install ) ;
t . lastuse = jiffies_to_clock_t ( jiffies - p - > tm . lastuse ) ;
t . expires = jiffies_to_clock_t ( p - > tm . expires ) ;
RTA_PUT ( skb , TCA_DEF_TM , sizeof ( t ) , & t ) ;
return skb - > len ;
rtattr_failure :
skb_trim ( skb , b - skb - > data ) ;
return - 1 ;
}
# define tca_use_default_ops \
. dump = tcf_defact_dump , \
. cleanup = tcf_defact_cleanup , \
. init = tcf_defact_init , \
. walk = tcf_generic_walker , \
# define tca_use_default_defines(name) \
static u32 idx_gen ; \
static struct tcf_defact * tcf_ # # name_ht [ MY_TAB_SIZE ] ; \
static DEFINE_RWLOCK ( # # name_lock ) ;
# endif /* _NET_ACT_GENERIC_H */