2008-09-13 03:30:20 +04:00
/*
* Copyright ( c ) 2008 , Intel Corporation .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
2013-12-06 21:13:44 +04:00
* this program ; if not , see < http : //www.gnu.org/licenses/>.
2008-09-13 03:30:20 +04:00
*
* Author : Alexander Duyck < alexander . h . duyck @ intel . com >
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/skbuff.h>
# include <linux/rtnetlink.h>
# include <net/netlink.h>
# include <net/pkt_sched.h>
2018-07-01 22:16:27 +03:00
# include <net/ip.h>
# include <net/ipv6.h>
# include <net/dsfield.h>
2019-03-20 17:00:11 +03:00
# include <net/pkt_cls.h>
2008-09-13 03:30:20 +04:00
# include <linux/tc_act/tc_skbedit.h>
# include <net/tc_act/tc_skbedit.h>
netns: make struct pernet_operations::id unsigned int
Make struct pernet_operations::id unsigned.
There are 2 reasons to do so:
1)
This field is really an index into an zero based array and
thus is unsigned entity. Using negative value is out-of-bound
access by definition.
2)
On x86_64 unsigned 32-bit data which are mixed with pointers
via array indexing or offsets added or subtracted to pointers
are preffered to signed 32-bit data.
"int" being used as an array index needs to be sign-extended
to 64-bit before being used.
void f(long *p, int i)
{
g(p[i]);
}
roughly translates to
movsx rsi, esi
mov rdi, [rsi+...]
call g
MOVSX is 3 byte instruction which isn't necessary if the variable is
unsigned because x86_64 is zero extending by default.
Now, there is net_generic() function which, you guessed it right, uses
"int" as an array index:
static inline void *net_generic(const struct net *net, int id)
{
...
ptr = ng->ptr[id - 1];
...
}
And this function is used a lot, so those sign extensions add up.
Patch snipes ~1730 bytes on allyesconfig kernel (without all junk
messing with code generation):
add/remove: 0/0 grow/shrink: 70/598 up/down: 396/-2126 (-1730)
Unfortunately some functions actually grow bigger.
This is a semmingly random artefact of code generation with register
allocator being used differently. gcc decides that some variable
needs to live in new r8+ registers and every access now requires REX
prefix. Or it is shifted into r12, so [r12+0] addressing mode has to be
used which is longer than [r8]
However, overall balance is in negative direction:
add/remove: 0/0 grow/shrink: 70/598 up/down: 396/-2126 (-1730)
function old new delta
nfsd4_lock 3886 3959 +73
tipc_link_build_proto_msg 1096 1140 +44
mac80211_hwsim_new_radio 2776 2808 +32
tipc_mon_rcv 1032 1058 +26
svcauth_gss_legacy_init 1413 1429 +16
tipc_bcbase_select_primary 379 392 +13
nfsd4_exchange_id 1247 1260 +13
nfsd4_setclientid_confirm 782 793 +11
...
put_client_renew_locked 494 480 -14
ip_set_sockfn_get 730 716 -14
geneve_sock_add 829 813 -16
nfsd4_sequence_done 721 703 -18
nlmclnt_lookup_host 708 686 -22
nfsd4_lockt 1085 1063 -22
nfs_get_client 1077 1050 -27
tcf_bpf_init 1106 1076 -30
nfsd4_encode_fattr 5997 5930 -67
Total: Before=154856051, After=154854321, chg -0.00%
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-11-17 04:58:21 +03:00
static unsigned int skbedit_net_id ;
2016-07-26 02:09:41 +03:00
static struct tc_action_ops act_skbedit_ops ;
2016-02-23 02:57:53 +03:00
2018-08-12 16:34:58 +03:00
static int tcf_skbedit_act ( struct sk_buff * skb , const struct tc_action * a ,
struct tcf_result * res )
2008-09-13 03:30:20 +04:00
{
2016-07-26 02:09:41 +03:00
struct tcf_skbedit * d = to_skbedit ( a ) ;
2018-07-11 17:04:50 +03:00
struct tcf_skbedit_params * params ;
int action ;
2008-09-13 03:30:20 +04:00
2016-06-06 13:32:53 +03:00
tcf_lastuse_update ( & d - > tcf_tm ) ;
2018-07-11 17:04:49 +03:00
bstats_cpu_update ( this_cpu_ptr ( d - > common . cpu_bstats ) , skb ) ;
2008-09-13 03:30:20 +04:00
2018-07-30 15:30:43 +03:00
params = rcu_dereference_bh ( d - > params ) ;
2018-07-11 17:04:50 +03:00
action = READ_ONCE ( d - > tcf_action ) ;
if ( params - > flags & SKBEDIT_F_PRIORITY )
skb - > priority = params - > priority ;
if ( params - > flags & SKBEDIT_F_INHERITDSFIELD ) {
2018-07-01 22:16:27 +03:00
int wlen = skb_network_offset ( skb ) ;
switch ( tc_skb_protocol ( skb ) ) {
case htons ( ETH_P_IP ) :
wlen + = sizeof ( struct iphdr ) ;
if ( ! pskb_may_pull ( skb , wlen ) )
goto err ;
skb - > priority = ipv4_get_dsfield ( ip_hdr ( skb ) ) > > 2 ;
break ;
case htons ( ETH_P_IPV6 ) :
wlen + = sizeof ( struct ipv6hdr ) ;
if ( ! pskb_may_pull ( skb , wlen ) )
goto err ;
skb - > priority = ipv6_get_dsfield ( ipv6_hdr ( skb ) ) > > 2 ;
break ;
}
}
2018-07-11 17:04:50 +03:00
if ( params - > flags & SKBEDIT_F_QUEUE_MAPPING & &
skb - > dev - > real_num_tx_queues > params - > queue_mapping )
skb_set_queue_mapping ( skb , params - > queue_mapping ) ;
if ( params - > flags & SKBEDIT_F_MARK ) {
skb - > mark & = ~ params - > mask ;
skb - > mark | = params - > mark & params - > mask ;
2016-10-24 15:32:57 +03:00
}
2018-07-11 17:04:50 +03:00
if ( params - > flags & SKBEDIT_F_PTYPE )
skb - > pkt_type = params - > ptype ;
return action ;
2018-07-30 15:30:43 +03:00
2018-07-01 22:16:27 +03:00
err :
2018-07-11 17:04:49 +03:00
qstats_drop_inc ( this_cpu_ptr ( d - > common . cpu_qstats ) ) ;
2018-07-30 15:30:43 +03:00
return TC_ACT_SHOT ;
2008-09-13 03:30:20 +04:00
}
static const struct nla_policy skbedit_policy [ TCA_SKBEDIT_MAX + 1 ] = {
[ TCA_SKBEDIT_PARMS ] = { . len = sizeof ( struct tc_skbedit ) } ,
[ TCA_SKBEDIT_PRIORITY ] = { . len = sizeof ( u32 ) } ,
[ TCA_SKBEDIT_QUEUE_MAPPING ] = { . len = sizeof ( u16 ) } ,
2009-10-15 07:09:18 +04:00
[ TCA_SKBEDIT_MARK ] = { . len = sizeof ( u32 ) } ,
2016-07-02 13:43:15 +03:00
[ TCA_SKBEDIT_PTYPE ] = { . len = sizeof ( u16 ) } ,
2016-10-24 15:32:57 +03:00
[ TCA_SKBEDIT_MASK ] = { . len = sizeof ( u32 ) } ,
2018-07-01 22:16:27 +03:00
[ TCA_SKBEDIT_FLAGS ] = { . len = sizeof ( u64 ) } ,
2008-09-13 03:30:20 +04:00
} ;
2013-01-14 09:15:39 +04:00
static int tcf_skbedit_init ( struct net * net , struct nlattr * nla ,
2016-07-26 02:09:41 +03:00
struct nlattr * est , struct tc_action * * a ,
2018-07-05 17:24:25 +03:00
int ovr , int bind , bool rtnl_held ,
net/sched: prepare TC actions to properly validate the control action
- pass a pointer to struct tcf_proto in each actions's init() handler,
to allow validating the control action, checking whether the chain
exists and (eventually) refcounting it.
- remove code that validates the control action after a successful call
to the action's init() handler, and replace it with a test that forbids
addition of actions having 'goto_chain' and NULL goto_chain pointer at
the same time.
- add tcf_action_check_ctrlact(), that will validate the control action
and eventually allocate the action 'goto_chain' within the init()
handler.
- add tcf_action_set_ctrlact(), that will assign the control action and
swap the current 'goto_chain' pointer with the new given one.
This disallows 'goto_chain' on actions that don't initialize it properly
in their init() handler, i.e. calling tcf_action_check_ctrlact() after
successful IDR reservation and then calling tcf_action_set_ctrlact()
to assign 'goto_chain' and 'tcf_action' consistently.
By doing this, the kernel does not leak anymore refcounts when a valid
'goto chain' handle is replaced in TC actions, causing kmemleak splats
like the following one:
# tc chain add dev dd0 chain 42 ingress protocol ip flower \
> ip_proto tcp action drop
# tc chain add dev dd0 chain 43 ingress protocol ip flower \
> ip_proto udp action drop
# tc filter add dev dd0 ingress matchall \
> action gact goto chain 42 index 66
# tc filter replace dev dd0 ingress matchall \
> action gact goto chain 43 index 66
# echo scan >/sys/kernel/debug/kmemleak
<...>
unreferenced object 0xffff93c0ee09f000 (size 1024):
comm "tc", pid 2565, jiffies 4295339808 (age 65.426s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 08 00 06 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<000000009b63f92d>] tc_ctl_chain+0x3d2/0x4c0
[<00000000683a8d72>] rtnetlink_rcv_msg+0x263/0x2d0
[<00000000ddd88f8e>] netlink_rcv_skb+0x4a/0x110
[<000000006126a348>] netlink_unicast+0x1a0/0x250
[<00000000b3340877>] netlink_sendmsg+0x2c1/0x3c0
[<00000000a25a2171>] sock_sendmsg+0x36/0x40
[<00000000f19ee1ec>] ___sys_sendmsg+0x280/0x2f0
[<00000000d0422042>] __sys_sendmsg+0x5e/0xa0
[<000000007a6c61f9>] do_syscall_64+0x5b/0x180
[<00000000ccd07542>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[<0000000013eaa334>] 0xffffffffffffffff
Fixes: db50514f9a9c ("net: sched: add termination action to allow goto chain")
Fixes: 97763dc0f401 ("net_sched: reject unknown tcfa_action values")
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-03-20 16:59:59 +03:00
struct tcf_proto * tp ,
2018-07-05 17:24:25 +03:00
struct netlink_ext_ack * extack )
2008-09-13 03:30:20 +04:00
{
2016-02-23 02:57:53 +03:00
struct tc_action_net * tn = net_generic ( net , skbedit_net_id ) ;
2018-09-03 10:07:15 +03:00
struct tcf_skbedit_params * params_new ;
2008-09-13 03:30:20 +04:00
struct nlattr * tb [ TCA_SKBEDIT_MAX + 1 ] ;
2019-03-20 17:00:11 +03:00
struct tcf_chain * goto_ch = NULL ;
2008-09-13 03:30:20 +04:00
struct tc_skbedit * parm ;
struct tcf_skbedit * d ;
2016-10-24 15:32:57 +03:00
u32 flags = 0 , * priority = NULL , * mark = NULL , * mask = NULL ;
2016-07-02 13:43:15 +03:00
u16 * queue_mapping = NULL , * ptype = NULL ;
2016-06-13 23:46:28 +03:00
bool exists = false ;
int ret = 0 , err ;
2008-09-13 03:30:20 +04:00
if ( nla = = NULL )
return - EINVAL ;
2017-04-12 15:34:07 +03:00
err = nla_parse_nested ( tb , TCA_SKBEDIT_MAX , nla , skbedit_policy , NULL ) ;
2008-09-13 03:30:20 +04:00
if ( err < 0 )
return err ;
if ( tb [ TCA_SKBEDIT_PARMS ] = = NULL )
return - EINVAL ;
if ( tb [ TCA_SKBEDIT_PRIORITY ] ! = NULL ) {
flags | = SKBEDIT_F_PRIORITY ;
priority = nla_data ( tb [ TCA_SKBEDIT_PRIORITY ] ) ;
}
if ( tb [ TCA_SKBEDIT_QUEUE_MAPPING ] ! = NULL ) {
flags | = SKBEDIT_F_QUEUE_MAPPING ;
queue_mapping = nla_data ( tb [ TCA_SKBEDIT_QUEUE_MAPPING ] ) ;
}
2009-10-15 07:09:18 +04:00
2016-07-02 13:43:15 +03:00
if ( tb [ TCA_SKBEDIT_PTYPE ] ! = NULL ) {
ptype = nla_data ( tb [ TCA_SKBEDIT_PTYPE ] ) ;
if ( ! skb_pkt_type_ok ( * ptype ) )
return - EINVAL ;
flags | = SKBEDIT_F_PTYPE ;
}
2009-10-15 07:09:18 +04:00
if ( tb [ TCA_SKBEDIT_MARK ] ! = NULL ) {
flags | = SKBEDIT_F_MARK ;
mark = nla_data ( tb [ TCA_SKBEDIT_MARK ] ) ;
}
2016-10-24 15:32:57 +03:00
if ( tb [ TCA_SKBEDIT_MASK ] ! = NULL ) {
flags | = SKBEDIT_F_MASK ;
mask = nla_data ( tb [ TCA_SKBEDIT_MASK ] ) ;
}
2018-07-01 22:16:27 +03:00
if ( tb [ TCA_SKBEDIT_FLAGS ] ! = NULL ) {
u64 * pure_flags = nla_data ( tb [ TCA_SKBEDIT_FLAGS ] ) ;
if ( * pure_flags & SKBEDIT_F_INHERITDSFIELD )
flags | = SKBEDIT_F_INHERITDSFIELD ;
}
2008-09-13 03:30:20 +04:00
parm = nla_data ( tb [ TCA_SKBEDIT_PARMS ] ) ;
2018-07-05 17:24:32 +03:00
err = tcf_idr_check_alloc ( tn , & parm - > index , a , bind ) ;
if ( err < 0 )
return err ;
exists = err ;
2016-05-10 23:49:30 +03:00
if ( exists & & bind )
return 0 ;
if ( ! flags ) {
2018-05-11 17:55:09 +03:00
if ( exists )
tcf_idr_release ( * a , bind ) ;
2018-07-05 17:24:32 +03:00
else
tcf_idr_cleanup ( tn , parm - > index ) ;
2016-05-10 23:49:30 +03:00
return - EINVAL ;
}
if ( ! exists ) {
2017-08-30 09:31:59 +03:00
ret = tcf_idr_create ( tn , parm - > index , est , a ,
2018-07-11 17:04:49 +03:00
& act_skbedit_ops , bind , true ) ;
2018-07-05 17:24:32 +03:00
if ( ret ) {
tcf_idr_cleanup ( tn , parm - > index ) ;
2014-02-12 05:07:31 +04:00
return ret ;
2018-07-05 17:24:32 +03:00
}
2008-09-13 03:30:20 +04:00
2016-07-26 02:09:41 +03:00
d = to_skbedit ( * a ) ;
2008-09-13 03:30:20 +04:00
ret = ACT_P_CREATED ;
} else {
2016-07-26 02:09:41 +03:00
d = to_skbedit ( * a ) ;
2018-07-05 17:24:30 +03:00
if ( ! ovr ) {
tcf_idr_release ( * a , bind ) ;
2008-09-13 03:30:20 +04:00
return - EEXIST ;
2018-07-05 17:24:30 +03:00
}
2008-09-13 03:30:20 +04:00
}
2019-03-20 17:00:11 +03:00
err = tcf_action_check_ctrlact ( parm - > action , tp , & goto_ch , extack ) ;
if ( err < 0 )
goto release_idr ;
2008-09-13 03:30:20 +04:00
2018-07-11 17:04:50 +03:00
params_new = kzalloc ( sizeof ( * params_new ) , GFP_KERNEL ) ;
if ( unlikely ( ! params_new ) ) {
2019-03-20 17:00:11 +03:00
err = - ENOMEM ;
goto put_chain ;
2018-07-11 17:04:50 +03:00
}
params_new - > flags = flags ;
2008-09-13 03:30:20 +04:00
if ( flags & SKBEDIT_F_PRIORITY )
2018-07-11 17:04:50 +03:00
params_new - > priority = * priority ;
2008-09-13 03:30:20 +04:00
if ( flags & SKBEDIT_F_QUEUE_MAPPING )
2018-07-11 17:04:50 +03:00
params_new - > queue_mapping = * queue_mapping ;
2009-10-15 07:09:18 +04:00
if ( flags & SKBEDIT_F_MARK )
2018-07-11 17:04:50 +03:00
params_new - > mark = * mark ;
2016-07-02 13:43:15 +03:00
if ( flags & SKBEDIT_F_PTYPE )
2018-07-11 17:04:50 +03:00
params_new - > ptype = * ptype ;
2016-10-24 15:32:57 +03:00
/* default behaviour is to use all the bits */
2018-07-11 17:04:50 +03:00
params_new - > mask = 0xffffffff ;
2016-10-24 15:32:57 +03:00
if ( flags & SKBEDIT_F_MASK )
2018-07-11 17:04:50 +03:00
params_new - > mask = * mask ;
2009-10-15 07:09:18 +04:00
2018-09-03 10:07:15 +03:00
spin_lock_bh ( & d - > tcf_lock ) ;
2019-03-20 17:00:11 +03:00
goto_ch = tcf_action_set_ctrlact ( * a , parm - > action , goto_ch ) ;
2018-09-03 10:07:15 +03:00
rcu_swap_protected ( d - > params , params_new ,
lockdep_is_held ( & d - > tcf_lock ) ) ;
spin_unlock_bh ( & d - > tcf_lock ) ;
if ( params_new )
kfree_rcu ( params_new , rcu ) ;
2019-03-20 17:00:11 +03:00
if ( goto_ch )
tcf_chain_put_by_act ( goto_ch ) ;
2008-09-13 03:30:20 +04:00
if ( ret = = ACT_P_CREATED )
2017-08-30 09:31:59 +03:00
tcf_idr_insert ( tn , * a ) ;
2008-09-13 03:30:20 +04:00
return ret ;
2019-03-20 17:00:11 +03:00
put_chain :
if ( goto_ch )
tcf_chain_put_by_act ( goto_ch ) ;
release_idr :
tcf_idr_release ( * a , bind ) ;
return err ;
2008-09-13 03:30:20 +04:00
}
2011-01-19 22:26:56 +03:00
static int tcf_skbedit_dump ( struct sk_buff * skb , struct tc_action * a ,
int bind , int ref )
2008-09-13 03:30:20 +04:00
{
unsigned char * b = skb_tail_pointer ( skb ) ;
2016-07-26 02:09:41 +03:00
struct tcf_skbedit * d = to_skbedit ( a ) ;
2018-07-11 17:04:50 +03:00
struct tcf_skbedit_params * params ;
2010-08-17 00:04:22 +04:00
struct tc_skbedit opt = {
. index = d - > tcf_index ,
2018-07-05 17:24:24 +03:00
. refcnt = refcount_read ( & d - > tcf_refcnt ) - ref ,
. bindcnt = atomic_read ( & d - > tcf_bindcnt ) - bind ,
2010-08-17 00:04:22 +04:00
} ;
2018-07-01 22:16:27 +03:00
u64 pure_flags = 0 ;
2018-07-11 17:04:50 +03:00
struct tcf_t t ;
2018-09-03 10:07:15 +03:00
spin_lock_bh ( & d - > tcf_lock ) ;
params = rcu_dereference_protected ( d - > params ,
lockdep_is_held ( & d - > tcf_lock ) ) ;
opt . action = d - > tcf_action ;
2008-09-13 03:30:20 +04:00
2012-03-29 13:11:39 +04:00
if ( nla_put ( skb , TCA_SKBEDIT_PARMS , sizeof ( opt ) , & opt ) )
goto nla_put_failure ;
2018-07-11 17:04:50 +03:00
if ( ( params - > flags & SKBEDIT_F_PRIORITY ) & &
nla_put_u32 ( skb , TCA_SKBEDIT_PRIORITY , params - > priority ) )
2012-03-29 13:11:39 +04:00
goto nla_put_failure ;
2018-07-11 17:04:50 +03:00
if ( ( params - > flags & SKBEDIT_F_QUEUE_MAPPING ) & &
nla_put_u16 ( skb , TCA_SKBEDIT_QUEUE_MAPPING , params - > queue_mapping ) )
2012-03-29 13:11:39 +04:00
goto nla_put_failure ;
2018-07-11 17:04:50 +03:00
if ( ( params - > flags & SKBEDIT_F_MARK ) & &
nla_put_u32 ( skb , TCA_SKBEDIT_MARK , params - > mark ) )
2012-03-29 13:11:39 +04:00
goto nla_put_failure ;
2018-07-11 17:04:50 +03:00
if ( ( params - > flags & SKBEDIT_F_PTYPE ) & &
nla_put_u16 ( skb , TCA_SKBEDIT_PTYPE , params - > ptype ) )
2016-07-02 13:43:15 +03:00
goto nla_put_failure ;
2018-07-11 17:04:50 +03:00
if ( ( params - > flags & SKBEDIT_F_MASK ) & &
nla_put_u32 ( skb , TCA_SKBEDIT_MASK , params - > mask ) )
2016-10-24 15:32:57 +03:00
goto nla_put_failure ;
2018-07-11 17:04:50 +03:00
if ( params - > flags & SKBEDIT_F_INHERITDSFIELD )
2018-07-01 22:16:27 +03:00
pure_flags | = SKBEDIT_F_INHERITDSFIELD ;
if ( pure_flags ! = 0 & &
nla_put ( skb , TCA_SKBEDIT_FLAGS , sizeof ( pure_flags ) , & pure_flags ) )
goto nla_put_failure ;
2016-06-06 13:32:55 +03:00
tcf_tm_dump ( & t , & d - > tcf_tm ) ;
2016-04-26 11:06:18 +03:00
if ( nla_put_64bit ( skb , TCA_SKBEDIT_TM , sizeof ( t ) , & t , TCA_SKBEDIT_PAD ) )
2012-03-29 13:11:39 +04:00
goto nla_put_failure ;
2018-09-03 10:07:15 +03:00
spin_unlock_bh ( & d - > tcf_lock ) ;
2008-09-13 03:30:20 +04:00
return skb - > len ;
nla_put_failure :
2018-09-03 10:07:15 +03:00
spin_unlock_bh ( & d - > tcf_lock ) ;
2008-09-13 03:30:20 +04:00
nlmsg_trim ( skb , b ) ;
return - 1 ;
}
2018-07-11 17:04:50 +03:00
static void tcf_skbedit_cleanup ( struct tc_action * a )
{
struct tcf_skbedit * d = to_skbedit ( a ) ;
struct tcf_skbedit_params * params ;
params = rcu_dereference_protected ( d - > params , 1 ) ;
if ( params )
kfree_rcu ( params , rcu ) ;
}
2016-02-23 02:57:53 +03:00
static int tcf_skbedit_walker ( struct net * net , struct sk_buff * skb ,
struct netlink_callback * cb , int type ,
2018-02-15 18:54:58 +03:00
const struct tc_action_ops * ops ,
struct netlink_ext_ack * extack )
2016-02-23 02:57:53 +03:00
{
struct tc_action_net * tn = net_generic ( net , skbedit_net_id ) ;
2018-02-15 18:54:59 +03:00
return tcf_generic_walker ( tn , skb , cb , type , ops , extack ) ;
2016-02-23 02:57:53 +03:00
}
2018-08-29 20:15:35 +03:00
static int tcf_skbedit_search ( struct net * net , struct tc_action * * a , u32 index )
2016-02-23 02:57:53 +03:00
{
struct tc_action_net * tn = net_generic ( net , skbedit_net_id ) ;
2017-08-30 09:31:59 +03:00
return tcf_idr_search ( tn , a , index ) ;
2016-02-23 02:57:53 +03:00
}
2008-09-13 03:30:20 +04:00
static struct tc_action_ops act_skbedit_ops = {
. kind = " skbedit " ,
2019-02-10 15:25:00 +03:00
. id = TCA_ID_SKBEDIT ,
2008-09-13 03:30:20 +04:00
. owner = THIS_MODULE ,
2018-08-12 16:34:58 +03:00
. act = tcf_skbedit_act ,
2008-09-13 03:30:20 +04:00
. dump = tcf_skbedit_dump ,
. init = tcf_skbedit_init ,
2018-07-11 17:04:50 +03:00
. cleanup = tcf_skbedit_cleanup ,
2016-02-23 02:57:53 +03:00
. walk = tcf_skbedit_walker ,
. lookup = tcf_skbedit_search ,
2016-07-26 02:09:41 +03:00
. size = sizeof ( struct tcf_skbedit ) ,
2016-02-23 02:57:53 +03:00
} ;
static __net_init int skbedit_init_net ( struct net * net )
{
struct tc_action_net * tn = net_generic ( net , skbedit_net_id ) ;
2017-11-07 00:47:18 +03:00
return tc_action_net_init ( tn , & act_skbedit_ops ) ;
2016-02-23 02:57:53 +03:00
}
2017-12-12 02:35:03 +03:00
static void __net_exit skbedit_exit_net ( struct list_head * net_list )
2016-02-23 02:57:53 +03:00
{
2017-12-12 02:35:03 +03:00
tc_action_net_exit ( net_list , skbedit_net_id ) ;
2016-02-23 02:57:53 +03:00
}
static struct pernet_operations skbedit_net_ops = {
. init = skbedit_init_net ,
2017-12-12 02:35:03 +03:00
. exit_batch = skbedit_exit_net ,
2016-02-23 02:57:53 +03:00
. id = & skbedit_net_id ,
. size = sizeof ( struct tc_action_net ) ,
2008-09-13 03:30:20 +04:00
} ;
MODULE_AUTHOR ( " Alexander Duyck, <alexander.h.duyck@intel.com> " ) ;
MODULE_DESCRIPTION ( " SKB Editing " ) ;
MODULE_LICENSE ( " GPL " ) ;
static int __init skbedit_init_module ( void )
{
2016-02-23 02:57:53 +03:00
return tcf_register_action ( & act_skbedit_ops , & skbedit_net_ops ) ;
2008-09-13 03:30:20 +04:00
}
static void __exit skbedit_cleanup_module ( void )
{
2016-02-23 02:57:53 +03:00
tcf_unregister_action ( & act_skbedit_ops , & skbedit_net_ops ) ;
2008-09-13 03:30:20 +04:00
}
module_init ( skbedit_init_module ) ;
module_exit ( skbedit_cleanup_module ) ;