Message ID | 20180331082232.13889-1-harshasharmaiitr@gmail.com |
---|---|
State | RFC |
Delegated to: | Pablo Neira |
Headers | show |
Series | [WIP,nf-next] netfilter: nft_ct: add ct timeout support | expand |
On Sat, Mar 31, 2018 at 01:52:32PM +0530, Harsha Sharma wrote: > This patch allows to add, list and delete connection tracking timeout > policy via nft objref infrastructure. > > Signed-off-by: Harsha Sharma <harshasharmaiitr@gmail.com> > --- > include/net/netfilter/nf_conntrack_timeout.h | 1 + > include/uapi/linux/netfilter/nf_tables.h | 15 ++- > net/netfilter/nft_ct.c | 167 ++++++++++++++++++++++++++- > 3 files changed, 180 insertions(+), 3 deletions(-) > > diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h > index 9468ab4ad12d..ae0f59cc1ffa 100644 > --- a/include/net/netfilter/nf_conntrack_timeout.h > +++ b/include/net/netfilter/nf_conntrack_timeout.h > @@ -8,6 +8,7 @@ > #include <linux/refcount.h> > #include <net/netfilter/nf_conntrack.h> > #include <net/netfilter/nf_conntrack_extend.h> > +#include <net/netfilter/nf_conntrack_l4proto.h> > > #define CTNL_TIMEOUT_NAME_MAX 32 > > diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h > index 66dceee0ae30..5762388e89dd 100644 > --- a/include/uapi/linux/netfilter/nf_tables.h > +++ b/include/uapi/linux/netfilter/nf_tables.h > @@ -920,6 +920,7 @@ enum nft_rt_attributes { > * @NFT_CT_AVGPKT: conntrack average bytes per packet > * @NFT_CT_ZONE: conntrack zone > * @NFT_CT_EVENTMASK: ctnetlink events to be generated for this conntrack > + * @NFT_CT_TIMEOUT: connection tracking timeout policy assigned to conntrack > */ > enum nft_ct_keys { > NFT_CT_STATE, > @@ -941,6 +942,7 @@ enum nft_ct_keys { > NFT_CT_AVGPKT, > NFT_CT_ZONE, > NFT_CT_EVENTMASK, > + NFT_CT_TIMEOUT, > }; > > /** > @@ -1302,12 +1304,23 @@ enum nft_ct_helper_attributes { > }; > #define NFTA_CT_HELPER_MAX (__NFTA_CT_HELPER_MAX - 1) > > +enum nft_ct_timeout_timeout_attributes { > + NFTA_CT_TIMEOUT_UNSPEC, > + NFTA_CT_TIMEOUT_L3PROTO, > + NFTA_CT_TIMEOUT_L4PROTO, > + NFTA_CT_TIMEOUT_DATA, > + NFTA_CT_TIMEOUT_USE, > + __NFTA_CT_TIMEOUT_MAX, > +}; > +#define NFTA_CT_TIMEOUT_MAX (__NFTA_CT_TIMEOUT_MAX - 1) > + > #define NFT_OBJECT_UNSPEC 0 > #define NFT_OBJECT_COUNTER 1 > #define NFT_OBJECT_QUOTA 2 > #define NFT_OBJECT_CT_HELPER 3 > #define NFT_OBJECT_LIMIT 4 > -#define __NFT_OBJECT_MAX 5 > +#define NFT_OBJECT_CT_TIMEOUT 5 > +#define __NFT_OBJECT_MAX 6 > #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) > > /** > diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c > index 6ab274b14484..e7af9781e4c1 100644 > --- a/net/netfilter/nft_ct.c > +++ b/net/netfilter/nft_ct.c > @@ -22,6 +22,9 @@ > #include <net/netfilter/nf_conntrack_helper.h> > #include <net/netfilter/nf_conntrack_ecache.h> > #include <net/netfilter/nf_conntrack_labels.h> > +#include <linux/netfilter/nfnetlink_cttimeout.h> > +#include <net/netfilter/nf_conntrack_timeout.h> > +#include <net/netfilter/nf_conntrack_l4proto.h> > > struct nft_ct { > enum nft_ct_keys key:8; > @@ -32,12 +35,16 @@ struct nft_ct { > }; > }; > > -struct nft_ct_helper_obj { > +struct nft_ct_helper_obj { > struct nf_conntrack_helper *helper4; > struct nf_conntrack_helper *helper6; > u8 l4proto; > }; > > +struct nft_ct_timeout_obj { > + struct ctnl_timeout *timeout; > +}; > + > #ifdef CONFIG_NF_CONNTRACK_ZONES > static DEFINE_PER_CPU(struct nf_conn *, nft_ct_pcpu_template); > static unsigned int nft_ct_pcpu_template_refcnt __read_mostly; > @@ -392,7 +399,6 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, > return -EINVAL; > len = NF_CT_HELPER_NAME_LEN; > break; > - > case NFT_CT_L3PROTOCOL: > case NFT_CT_PROTOCOL: > /* For compatibility, do not report error if NFTA_CT_DIRECTION > @@ -727,6 +733,134 @@ static struct nft_expr_type nft_notrack_type __read_mostly = { > .owner = THIS_MODULE, > }; > > +static int > +ctnl_timeout_parse_policy(void *timeouts, > + const struct nf_conntrack_l4proto *l4proto, > + struct net *net, const struct nlattr *attr) > +{ > + int ret = 0; > + > + if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { Remove all likely() and unlikely() in this code, I know you took it from nfnetlink_cttimeout.c but we don't need it. > + struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max + 1]; Use no VLA here, it seems some people don't like it, instead you can do like what we do in more recent code: https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git/tree/net/netfilter/nfnetlink_cttimeout.c#n57 Would you add _eval() code too? It will be very similar to nft_ct_helper_obj_eval(). After that change, you will need to extend userspace to allow to set timeouts, have a look at: commit 8675f943e7eff24f29aaa492cb58267f9291de31 commit 1ed84c4626973cee92e4a238ad55f7ba1f5af249 commit aabb9c46ac4cfdff3aad136dd2ed7cb2bb0f9293 commit ec38e5ed61a088a1fbd2922742c9125aa1c63a7c commit 5ca4eb30d62e0ab2768d64de5c70931292213338 It should be similar to that. I remember you told me that you were hitting problems with parser when adding the ct timeout states, skip that, we'll fix it at the end. Thanks. -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Harsha, Thank you for the patch! Yet something to improve: [auto build test ERROR on nf/master] [also build test ERROR on v4.16-rc7] [cannot apply to nf-next/master next-20180329] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Harsha-Sharma/netfilter-nft_ct-add-ct-timeout-support/20180401-070944 base: https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master config: i386-randconfig-x073-201813 (attached as .config) compiler: gcc-7 (Debian 7.3.0-1) 7.3.0 reproduce: # save the attached .config to linux build tree make ARCH=i386 All error/warnings (new ones prefixed by >>): In file included from include/linux/kernel.h:10:0, from net//netfilter/nft_ct.c:12: net//netfilter/nft_ct.c: In function 'ctnl_timeout_parse_policy': >> net//netfilter/nft_ct.c:743:22: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { ^ include/linux/compiler.h:76:40: note: in definition of macro 'likely' # define likely(x) __builtin_expect(!!(x), 1) ^ net//netfilter/nft_ct.c:744:30: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max + 1]; ^~~~~~~~~~~~ get_timeouts net//netfilter/nft_ct.c:746:39: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, ^~~~~~~~~~~~ get_timeouts net//netfilter/nft_ct.c:747:27: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? attr, l4proto->ctnl_timeout.nla_policy, ^~~~~~~~~~~~ get_timeouts net//netfilter/nft_ct.c:752:18: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts); ^~~~~~~~~~~~ get_timeouts net//netfilter/nft_ct.c:744:18: warning: unused variable 'tb' [-Wunused-variable] struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max + 1]; ^~ net//netfilter/nft_ct.c: In function 'nft_ct_timeout_obj_init': >> net//netfilter/nft_ct.c:782:26: error: 'struct net' has no member named 'nfct_timeout_list' INIT_LIST_HEAD(&ctx->net->nfct_timeout_list); ^~ In file included from net//netfilter/nft_ct.c:12:0: net//netfilter/nft_ct.c:783:40: error: 'struct net' has no member named 'nfct_timeout_list' list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^ include/linux/kernel.h:930:26: note: in definition of macro 'container_of' void *__mptr = (void *)(ptr); \ ^~~ include/linux/list.h:377:2: note: in expansion of macro 'list_entry' list_entry((ptr)->next, type, member) ^~~~~~~~~~ include/linux/list.h:464:13: note: in expansion of macro 'list_first_entry' for (pos = list_first_entry(head, typeof(*pos), member); \ ^~~~~~~~~~~~~~~~ >> net//netfilter/nft_ct.c:783:2: note: in expansion of macro 'list_for_each_entry' list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^~~~~~~~~~~~~~~~~~~ In file included from include/linux/kernel.h:10:0, from net//netfilter/nft_ct.c:12: net//netfilter/nft_ct.c:783:40: error: 'struct net' has no member named 'nfct_timeout_list' list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^ include/linux/compiler.h:316:19: note: in definition of macro '__compiletime_assert' bool __cond = !(condition); \ ^~~~~~~~~ include/linux/compiler.h:339:2: note: in expansion of macro '_compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:45:37: note: in expansion of macro 'compiletime_assert' #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^~~~~~~~~~~~~~~~~~ include/linux/kernel.h:931:2: note: in expansion of macro 'BUILD_BUG_ON_MSG' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^~~~~~~~~~~~~~~~ include/linux/kernel.h:931:20: note: in expansion of macro '__same_type' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^~~~~~~~~~~ include/linux/list.h:366:2: note: in expansion of macro 'container_of' container_of(ptr, type, member) ^~~~~~~~~~~~ include/linux/list.h:377:2: note: in expansion of macro 'list_entry' list_entry((ptr)->next, type, member) ^~~~~~~~~~ include/linux/list.h:464:13: note: in expansion of macro 'list_first_entry' for (pos = list_first_entry(head, typeof(*pos), member); \ ^~~~~~~~~~~~~~~~ >> net//netfilter/nft_ct.c:783:2: note: in expansion of macro 'list_for_each_entry' list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^~~~~~~~~~~~~~~~~~~ net//netfilter/nft_ct.c:783:40: error: 'struct net' has no member named 'nfct_timeout_list' list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^ include/linux/compiler.h:316:19: note: in definition of macro '__compiletime_assert' bool __cond = !(condition); \ ^~~~~~~~~ include/linux/compiler.h:339:2: note: in expansion of macro '_compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:45:37: note: in expansion of macro 'compiletime_assert' #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^~~~~~~~~~~~~~~~~~ include/linux/kernel.h:931:2: note: in expansion of macro 'BUILD_BUG_ON_MSG' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^~~~~~~~~~~~~~~~ include/linux/kernel.h:932:6: note: in expansion of macro '__same_type' !__same_type(*(ptr), void), \ ^~~~~~~~~~~ include/linux/list.h:366:2: note: in expansion of macro 'container_of' container_of(ptr, type, member) ^~~~~~~~~~~~ include/linux/list.h:377:2: note: in expansion of macro 'list_entry' list_entry((ptr)->next, type, member) ^~~~~~~~~~ include/linux/list.h:464:13: note: in expansion of macro 'list_first_entry' for (pos = list_first_entry(head, typeof(*pos), member); \ ^~~~~~~~~~~~~~~~ >> net//netfilter/nft_ct.c:783:2: note: in expansion of macro 'list_for_each_entry' list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^~~~~~~~~~~~~~~~~~~ In file included from include/linux/module.h:9:0, from net//netfilter/nft_ct.c:14: net//netfilter/nft_ct.c:783:40: error: 'struct net' has no member named 'nfct_timeout_list' list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^ include/linux/list.h:465:24: note: in definition of macro 'list_for_each_entry' &pos->member != (head); \ ^~~~ net//netfilter/nft_ct.c:805:15: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? l4proto->ctnl_timeout.obj_size, GFP_KERNEL); ^~~~~~~~~~~~ get_timeouts net//netfilter/nft_ct.c:817:45: error: 'struct net' has no member named 'nfct_timeout_list' list_add_tail_rcu(&timeout->head, &ctx->net->nfct_timeout_list); ^~ In file included from include/linux/kernel.h:10:0, from net//netfilter/nft_ct.c:12: net//netfilter/nft_ct.c: In function 'nft_ct_timeout_obj_dump': net//netfilter/nft_ct.c:848:31: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? if (likely(timeout->l4proto->ctnl_timeout.obj_to_nlattr)) { ^ include/linux/compiler.h:76:40: note: in definition of macro 'likely' # define likely(x) __builtin_expect(!!(x), 1) ^ net//netfilter/nft_ct.c:856:27: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? ret = timeout->l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data); ^~~~~~~~~~~~ get_timeouts vim +743 net//netfilter/nft_ct.c 735 736 static int 737 ctnl_timeout_parse_policy(void *timeouts, 738 const struct nf_conntrack_l4proto *l4proto, 739 struct net *net, const struct nlattr *attr) 740 { 741 int ret = 0; 742 > 743 if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { 744 struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max + 1]; 745 746 ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, 747 attr, l4proto->ctnl_timeout.nla_policy, 748 NULL); 749 if (ret < 0) 750 return ret; 751 > 752 ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts); 753 } 754 return ret; 755 } 756 757 static void nft_ct_timeout_obj_eval(struct nft_object *obj, 758 struct nft_regs *regs, 759 const struct nft_pktinfo *pkt) 760 { 761 } 762 763 static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx, 764 const struct nlattr * const tb[], 765 struct nft_object *obj) 766 { 767 __u16 l3num; 768 __u8 l4num; 769 struct nft_ct_timeout_obj *priv = nft_obj_data(obj); 770 const struct nf_conntrack_l4proto *l4proto; 771 struct ctnl_timeout *timeout, *matching = NULL; 772 int ret; 773 774 if (!tb[NFTA_CT_TIMEOUT_L4PROTO] || 775 !tb[NFTA_CT_TIMEOUT_L3PROTO] || 776 !tb[NFTA_CT_TIMEOUT_DATA]) 777 return -EINVAL; 778 779 l3num = ntohs(nla_get_be16(tb[NFTA_CT_TIMEOUT_L3PROTO])); 780 l4num = nla_get_u8(tb[NFTA_CT_TIMEOUT_L4PROTO]); 781 > 782 INIT_LIST_HEAD(&ctx->net->nfct_timeout_list); > 783 list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { 784 matching = timeout; 785 break; 786 } 787 788 if (matching) { 789 if (matching->l3num != l3num || 790 matching->l4proto->l4proto != l4num) 791 return -EINVAL; 792 return ctnl_timeout_parse_policy(&matching->data, 793 matching->l4proto, ctx->net, 794 tb[NFTA_CT_TIMEOUT_DATA]); 795 } 796 797 l4proto = nf_ct_l4proto_find_get(l3num, l4num); 798 799 if (l4proto->l4proto != l4num) { 800 ret = -EOPNOTSUPP; 801 goto err_proto_put; 802 } 803 804 timeout = kzalloc(sizeof(struct ctnl_timeout) + 805 l4proto->ctnl_timeout.obj_size, GFP_KERNEL); 806 if (timeout == NULL) { 807 ret = -ENOMEM; 808 goto err_proto_put; 809 } 810 811 ret = ctnl_timeout_parse_policy(&timeout->data, l4proto, ctx->net, 812 tb[NFTA_CT_TIMEOUT_DATA]); 813 if (ret < 0) 814 goto err; 815 timeout->l3num = l3num; 816 timeout->l4proto = l4proto; 817 list_add_tail_rcu(&timeout->head, &ctx->net->nfct_timeout_list); 818 priv->timeout = timeout; 819 820 return 0; 821 err: 822 kfree(timeout); 823 err_proto_put: 824 nf_ct_l4proto_put(l4proto); 825 return ret; 826 } 827 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Harsha, Thank you for the patch! Yet something to improve: [auto build test ERROR on nf/master] [also build test ERROR on v4.16-rc7] [cannot apply to nf-next/master next-20180329] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Harsha-Sharma/netfilter-nft_ct-add-ct-timeout-support/20180401-070944 base: https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master config: x86_64-rhel (attached as .config) compiler: gcc-7 (Debian 7.3.0-1) 7.3.0 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): In file included from include/linux/kernel.h:10:0, from net//netfilter/nft_ct.c:12: net//netfilter/nft_ct.c: In function 'ctnl_timeout_parse_policy': net//netfilter/nft_ct.c:743:22: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { ^ include/linux/compiler.h:76:40: note: in definition of macro 'likely' # define likely(x) __builtin_expect(!!(x), 1) ^ net//netfilter/nft_ct.c:744:30: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max + 1]; ^~~~~~~~~~~~ get_timeouts net//netfilter/nft_ct.c:746:39: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, ^~~~~~~~~~~~ get_timeouts net//netfilter/nft_ct.c:747:27: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? attr, l4proto->ctnl_timeout.nla_policy, ^~~~~~~~~~~~ get_timeouts net//netfilter/nft_ct.c:752:18: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts); ^~~~~~~~~~~~ get_timeouts net//netfilter/nft_ct.c:744:18: warning: unused variable 'tb' [-Wunused-variable] struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max + 1]; ^~ net//netfilter/nft_ct.c: In function 'nft_ct_timeout_obj_init': >> net//netfilter/nft_ct.c:782:28: error: 'struct net' has no member named 'nfct_timeout_list'; did you mean 'nfnl_acct_list'? INIT_LIST_HEAD(&ctx->net->nfct_timeout_list); ^~~~~~~~~~~~~~~~~ nfnl_acct_list In file included from net//netfilter/nft_ct.c:12:0: net//netfilter/nft_ct.c:783:42: error: 'struct net' has no member named 'nfct_timeout_list'; did you mean 'nfnl_acct_list'? list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^ include/linux/kernel.h:930:26: note: in definition of macro 'container_of' void *__mptr = (void *)(ptr); \ ^~~ include/linux/list.h:377:2: note: in expansion of macro 'list_entry' list_entry((ptr)->next, type, member) ^~~~~~~~~~ include/linux/list.h:464:13: note: in expansion of macro 'list_first_entry' for (pos = list_first_entry(head, typeof(*pos), member); \ ^~~~~~~~~~~~~~~~ net//netfilter/nft_ct.c:783:2: note: in expansion of macro 'list_for_each_entry' list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^~~~~~~~~~~~~~~~~~~ In file included from include/linux/kernel.h:10:0, from net//netfilter/nft_ct.c:12: net//netfilter/nft_ct.c:783:42: error: 'struct net' has no member named 'nfct_timeout_list'; did you mean 'nfnl_acct_list'? list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^ include/linux/compiler.h:316:19: note: in definition of macro '__compiletime_assert' bool __cond = !(condition); \ ^~~~~~~~~ include/linux/compiler.h:339:2: note: in expansion of macro '_compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:45:37: note: in expansion of macro 'compiletime_assert' #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^~~~~~~~~~~~~~~~~~ include/linux/kernel.h:931:2: note: in expansion of macro 'BUILD_BUG_ON_MSG' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^~~~~~~~~~~~~~~~ include/linux/kernel.h:931:20: note: in expansion of macro '__same_type' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^~~~~~~~~~~ include/linux/list.h:366:2: note: in expansion of macro 'container_of' container_of(ptr, type, member) ^~~~~~~~~~~~ include/linux/list.h:377:2: note: in expansion of macro 'list_entry' list_entry((ptr)->next, type, member) ^~~~~~~~~~ include/linux/list.h:464:13: note: in expansion of macro 'list_first_entry' for (pos = list_first_entry(head, typeof(*pos), member); \ ^~~~~~~~~~~~~~~~ net//netfilter/nft_ct.c:783:2: note: in expansion of macro 'list_for_each_entry' list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^~~~~~~~~~~~~~~~~~~ net//netfilter/nft_ct.c:783:42: error: 'struct net' has no member named 'nfct_timeout_list'; did you mean 'nfnl_acct_list'? list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^ include/linux/compiler.h:316:19: note: in definition of macro '__compiletime_assert' bool __cond = !(condition); \ ^~~~~~~~~ include/linux/compiler.h:339:2: note: in expansion of macro '_compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:45:37: note: in expansion of macro 'compiletime_assert' #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^~~~~~~~~~~~~~~~~~ include/linux/kernel.h:931:2: note: in expansion of macro 'BUILD_BUG_ON_MSG' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^~~~~~~~~~~~~~~~ include/linux/kernel.h:932:6: note: in expansion of macro '__same_type' !__same_type(*(ptr), void), \ ^~~~~~~~~~~ include/linux/list.h:366:2: note: in expansion of macro 'container_of' container_of(ptr, type, member) ^~~~~~~~~~~~ include/linux/list.h:377:2: note: in expansion of macro 'list_entry' list_entry((ptr)->next, type, member) ^~~~~~~~~~ include/linux/list.h:464:13: note: in expansion of macro 'list_first_entry' for (pos = list_first_entry(head, typeof(*pos), member); \ ^~~~~~~~~~~~~~~~ net//netfilter/nft_ct.c:783:2: note: in expansion of macro 'list_for_each_entry' list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^~~~~~~~~~~~~~~~~~~ In file included from include/linux/module.h:9:0, from net//netfilter/nft_ct.c:14: net//netfilter/nft_ct.c:783:42: error: 'struct net' has no member named 'nfct_timeout_list'; did you mean 'nfnl_acct_list'? list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { ^ include/linux/list.h:465:24: note: in definition of macro 'list_for_each_entry' &pos->member != (head); \ ^~~~ net//netfilter/nft_ct.c:805:15: error: 'const struct nf_conntrack_l4proto' has no member named 'ctnl_timeout'; did you mean 'get_timeouts'? l4proto->ctnl_timeout.obj_size, GFP_KERNEL); ^~~~~~~~~~~~ get_timeouts net//netfilter/nft_ct.c:817:47: error: 'struct net' has no member named 'nfct_timeout_list'; did you mean 'nfnl_acct_list'? list_add_tail_rcu(&timeout->head, &ctx->net->nfct_timeout_list); ^~~~~~~~~~~~~~~~~ nfnl_acct_list In file included from include/linux/kernel.h:10:0, from net//netfilter/nft_ct.c:12: net//netfilter/nft_ct.c: In function 'nft_ct_timeout_obj_dump': vim +782 net//netfilter/nft_ct.c 735 736 static int 737 ctnl_timeout_parse_policy(void *timeouts, 738 const struct nf_conntrack_l4proto *l4proto, 739 struct net *net, const struct nlattr *attr) 740 { 741 int ret = 0; 742 743 if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { 744 struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max + 1]; 745 746 ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, 747 attr, l4proto->ctnl_timeout.nla_policy, 748 NULL); 749 if (ret < 0) 750 return ret; 751 > 752 ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts); 753 } 754 return ret; 755 } 756 757 static void nft_ct_timeout_obj_eval(struct nft_object *obj, 758 struct nft_regs *regs, 759 const struct nft_pktinfo *pkt) 760 { 761 } 762 763 static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx, 764 const struct nlattr * const tb[], 765 struct nft_object *obj) 766 { 767 __u16 l3num; 768 __u8 l4num; 769 struct nft_ct_timeout_obj *priv = nft_obj_data(obj); 770 const struct nf_conntrack_l4proto *l4proto; 771 struct ctnl_timeout *timeout, *matching = NULL; 772 int ret; 773 774 if (!tb[NFTA_CT_TIMEOUT_L4PROTO] || 775 !tb[NFTA_CT_TIMEOUT_L3PROTO] || 776 !tb[NFTA_CT_TIMEOUT_DATA]) 777 return -EINVAL; 778 779 l3num = ntohs(nla_get_be16(tb[NFTA_CT_TIMEOUT_L3PROTO])); 780 l4num = nla_get_u8(tb[NFTA_CT_TIMEOUT_L4PROTO]); 781 > 782 INIT_LIST_HEAD(&ctx->net->nfct_timeout_list); 783 list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { 784 matching = timeout; 785 break; 786 } 787 788 if (matching) { 789 if (matching->l3num != l3num || 790 matching->l4proto->l4proto != l4num) 791 return -EINVAL; 792 return ctnl_timeout_parse_policy(&matching->data, 793 matching->l4proto, ctx->net, 794 tb[NFTA_CT_TIMEOUT_DATA]); 795 } 796 797 l4proto = nf_ct_l4proto_find_get(l3num, l4num); 798 799 if (l4proto->l4proto != l4num) { 800 ret = -EOPNOTSUPP; 801 goto err_proto_put; 802 } 803 804 timeout = kzalloc(sizeof(struct ctnl_timeout) + 805 l4proto->ctnl_timeout.obj_size, GFP_KERNEL); 806 if (timeout == NULL) { 807 ret = -ENOMEM; 808 goto err_proto_put; 809 } 810 811 ret = ctnl_timeout_parse_policy(&timeout->data, l4proto, ctx->net, 812 tb[NFTA_CT_TIMEOUT_DATA]); 813 if (ret < 0) 814 goto err; 815 timeout->l3num = l3num; 816 timeout->l4proto = l4proto; 817 list_add_tail_rcu(&timeout->head, &ctx->net->nfct_timeout_list); 818 priv->timeout = timeout; 819 820 return 0; 821 err: 822 kfree(timeout); 823 err_proto_put: 824 nf_ct_l4proto_put(l4proto); 825 return ret; 826 } 827 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h index 9468ab4ad12d..ae0f59cc1ffa 100644 --- a/include/net/netfilter/nf_conntrack_timeout.h +++ b/include/net/netfilter/nf_conntrack_timeout.h @@ -8,6 +8,7 @@ #include <linux/refcount.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_extend.h> +#include <net/netfilter/nf_conntrack_l4proto.h> #define CTNL_TIMEOUT_NAME_MAX 32 diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 66dceee0ae30..5762388e89dd 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -920,6 +920,7 @@ enum nft_rt_attributes { * @NFT_CT_AVGPKT: conntrack average bytes per packet * @NFT_CT_ZONE: conntrack zone * @NFT_CT_EVENTMASK: ctnetlink events to be generated for this conntrack + * @NFT_CT_TIMEOUT: connection tracking timeout policy assigned to conntrack */ enum nft_ct_keys { NFT_CT_STATE, @@ -941,6 +942,7 @@ enum nft_ct_keys { NFT_CT_AVGPKT, NFT_CT_ZONE, NFT_CT_EVENTMASK, + NFT_CT_TIMEOUT, }; /** @@ -1302,12 +1304,23 @@ enum nft_ct_helper_attributes { }; #define NFTA_CT_HELPER_MAX (__NFTA_CT_HELPER_MAX - 1) +enum nft_ct_timeout_timeout_attributes { + NFTA_CT_TIMEOUT_UNSPEC, + NFTA_CT_TIMEOUT_L3PROTO, + NFTA_CT_TIMEOUT_L4PROTO, + NFTA_CT_TIMEOUT_DATA, + NFTA_CT_TIMEOUT_USE, + __NFTA_CT_TIMEOUT_MAX, +}; +#define NFTA_CT_TIMEOUT_MAX (__NFTA_CT_TIMEOUT_MAX - 1) + #define NFT_OBJECT_UNSPEC 0 #define NFT_OBJECT_COUNTER 1 #define NFT_OBJECT_QUOTA 2 #define NFT_OBJECT_CT_HELPER 3 #define NFT_OBJECT_LIMIT 4 -#define __NFT_OBJECT_MAX 5 +#define NFT_OBJECT_CT_TIMEOUT 5 +#define __NFT_OBJECT_MAX 6 #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) /** diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 6ab274b14484..e7af9781e4c1 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c @@ -22,6 +22,9 @@ #include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_conntrack_labels.h> +#include <linux/netfilter/nfnetlink_cttimeout.h> +#include <net/netfilter/nf_conntrack_timeout.h> +#include <net/netfilter/nf_conntrack_l4proto.h> struct nft_ct { enum nft_ct_keys key:8; @@ -32,12 +35,16 @@ struct nft_ct { }; }; -struct nft_ct_helper_obj { +struct nft_ct_helper_obj { struct nf_conntrack_helper *helper4; struct nf_conntrack_helper *helper6; u8 l4proto; }; +struct nft_ct_timeout_obj { + struct ctnl_timeout *timeout; +}; + #ifdef CONFIG_NF_CONNTRACK_ZONES static DEFINE_PER_CPU(struct nf_conn *, nft_ct_pcpu_template); static unsigned int nft_ct_pcpu_template_refcnt __read_mostly; @@ -392,7 +399,6 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, return -EINVAL; len = NF_CT_HELPER_NAME_LEN; break; - case NFT_CT_L3PROTOCOL: case NFT_CT_PROTOCOL: /* For compatibility, do not report error if NFTA_CT_DIRECTION @@ -727,6 +733,134 @@ static struct nft_expr_type nft_notrack_type __read_mostly = { .owner = THIS_MODULE, }; +static int +ctnl_timeout_parse_policy(void *timeouts, + const struct nf_conntrack_l4proto *l4proto, + struct net *net, const struct nlattr *attr) +{ + int ret = 0; + + if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { + struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max + 1]; + + ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, + attr, l4proto->ctnl_timeout.nla_policy, + NULL); + if (ret < 0) + return ret; + + ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts); + } + return ret; +} + +static void nft_ct_timeout_obj_eval(struct nft_object *obj, + struct nft_regs *regs, + const struct nft_pktinfo *pkt) +{ +} + +static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx, + const struct nlattr * const tb[], + struct nft_object *obj) +{ + __u16 l3num; + __u8 l4num; + struct nft_ct_timeout_obj *priv = nft_obj_data(obj); + const struct nf_conntrack_l4proto *l4proto; + struct ctnl_timeout *timeout, *matching = NULL; + int ret; + + if (!tb[NFTA_CT_TIMEOUT_L4PROTO] || + !tb[NFTA_CT_TIMEOUT_L3PROTO] || + !tb[NFTA_CT_TIMEOUT_DATA]) + return -EINVAL; + + l3num = ntohs(nla_get_be16(tb[NFTA_CT_TIMEOUT_L3PROTO])); + l4num = nla_get_u8(tb[NFTA_CT_TIMEOUT_L4PROTO]); + + INIT_LIST_HEAD(&ctx->net->nfct_timeout_list); + list_for_each_entry(timeout, &ctx->net->nfct_timeout_list, head) { + matching = timeout; + break; + } + + if (matching) { + if (matching->l3num != l3num || + matching->l4proto->l4proto != l4num) + return -EINVAL; + return ctnl_timeout_parse_policy(&matching->data, + matching->l4proto, ctx->net, + tb[NFTA_CT_TIMEOUT_DATA]); + } + + l4proto = nf_ct_l4proto_find_get(l3num, l4num); + + if (l4proto->l4proto != l4num) { + ret = -EOPNOTSUPP; + goto err_proto_put; + } + + timeout = kzalloc(sizeof(struct ctnl_timeout) + + l4proto->ctnl_timeout.obj_size, GFP_KERNEL); + if (timeout == NULL) { + ret = -ENOMEM; + goto err_proto_put; + } + + ret = ctnl_timeout_parse_policy(&timeout->data, l4proto, ctx->net, + tb[NFTA_CT_TIMEOUT_DATA]); + if (ret < 0) + goto err; + timeout->l3num = l3num; + timeout->l4proto = l4proto; + list_add_tail_rcu(&timeout->head, &ctx->net->nfct_timeout_list); + priv->timeout = timeout; + + return 0; +err: + kfree(timeout); +err_proto_put: + nf_ct_l4proto_put(l4proto); + return ret; +} + +static void nft_ct_timeout_obj_destroy(struct nft_object *obj) +{ + struct nft_ct_timeout_obj *priv = nft_obj_data(obj); + + if (refcount_dec_if_one(&priv->timeout->refcnt)) { + nf_ct_l4proto_put(priv->timeout->l4proto); + list_del_rcu(&priv->timeout->head); + } +} + +static int nft_ct_timeout_obj_dump(struct sk_buff *skb, + struct nft_object *obj, bool reset) +{ + const struct nft_ct_timeout_obj *priv = nft_obj_data(obj); + const struct ctnl_timeout *timeout = priv->timeout; + + if (nla_put_u8(skb, NFTA_CT_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) || + nla_put_be16(skb, NFTA_CT_TIMEOUT_L3PROTO, htons(priv->timeout->l3num))) + return -1; + + if (likely(timeout->l4proto->ctnl_timeout.obj_to_nlattr)) { + struct nlattr *nest_params; + int ret; + + nest_params = nla_nest_start(skb, NFTA_CT_TIMEOUT_DATA | NLA_F_NESTED); + if (!nest_params) + return -1; + + ret = timeout->l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data); + if (ret < 0) + return -1; + nla_nest_end(skb, nest_params); + } + return 0; +} + static int nft_ct_helper_obj_init(const struct nft_ctx *ctx, const struct nlattr * const tb[], struct nft_object *obj) @@ -889,6 +1023,30 @@ static struct nft_object_type nft_ct_helper_obj_type __read_mostly = { .owner = THIS_MODULE, }; +static const struct nla_policy nft_ct_timeout_policy[NFTA_CT_TIMEOUT_MAX + 1] = { + [NFTA_CT_TIMEOUT_L3PROTO] = {.type = NLA_U16 }, + [NFTA_CT_TIMEOUT_L4PROTO] = {.type = NLA_U8 }, + [NFTA_CT_TIMEOUT_DATA] = {.type = NLA_NESTED }, +}; + +static struct nft_object_type nft_ct_timeout_obj_type; +static const struct nft_object_ops nft_ct_timeout_obj_ops = { + .type = &nft_ct_timeout_obj_type, + .size = sizeof(struct nft_ct_timeout_obj), + .eval = nft_ct_timeout_obj_eval, + .init = nft_ct_timeout_obj_init, + .destroy = nft_ct_timeout_obj_destroy, + .dump = nft_ct_timeout_obj_dump, +}; + +static struct nft_object_type nft_ct_timeout_obj_type __read_mostly = { + .type = NFT_OBJECT_CT_TIMEOUT, + .ops = &nft_ct_timeout_obj_ops, + .maxattr = NFTA_CT_TIMEOUT_MAX, + .policy = nft_ct_timeout_policy, + .owner = THIS_MODULE, +}; + static int __init nft_ct_module_init(void) { int err; @@ -904,6 +1062,9 @@ static int __init nft_ct_module_init(void) goto err1; err = nft_register_obj(&nft_ct_helper_obj_type); + if (err < 0) + goto err2; + err = nft_register_obj(&nft_ct_timeout_obj_type); if (err < 0) goto err2; @@ -919,6 +1080,7 @@ static int __init nft_ct_module_init(void) static void __exit nft_ct_module_exit(void) { nft_unregister_obj(&nft_ct_helper_obj_type); + nft_unregister_obj(&nft_ct_timeout_obj_type); nft_unregister_expr(&nft_notrack_type); nft_unregister_expr(&nft_ct_type); } @@ -931,3 +1093,4 @@ MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); MODULE_ALIAS_NFT_EXPR("ct"); MODULE_ALIAS_NFT_EXPR("notrack"); MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_HELPER); +MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_TIMEOUT);
This patch allows to add, list and delete connection tracking timeout policy via nft objref infrastructure. Signed-off-by: Harsha Sharma <harshasharmaiitr@gmail.com> --- include/net/netfilter/nf_conntrack_timeout.h | 1 + include/uapi/linux/netfilter/nf_tables.h | 15 ++- net/netfilter/nft_ct.c | 167 ++++++++++++++++++++++++++- 3 files changed, 180 insertions(+), 3 deletions(-)