On 16 October 2016 at 15:42, Anders K. Pedersen | Cohaesio <akp@xxxxxxxxxxxx> wrote: > From: Anders K. Pedersen <akp@xxxxxxxxxxxx> > > Introduce basic infrastructure for nftables rt expression for routing > related data. Initially "rt classid" is implemented identical to "meta > rtclassid", since it is more logical to have this match in the routing > expression going forward. > > Signed-off-by: Anders K. Pedersen <akp@xxxxxxxxxxxx> > --- > include/net/netfilter/nft_rt.h | 23 +++++ > net/netfilter/Kconfig | 6 ++ > net/netfilter/Makefile | 1 + > net/netfilter/nft_rt.c | 145 ++++++++++++++++++++++++++++++ > 4 files changed, 175 insertions(+) > > diff --git a/include/net/netfilter/nft_rt.h b/include/net/netfilter/nft_rt.h > --- /dev/null > +++ b/include/net/netfilter/nft_rt.h > @@ -0,0 +1,23 @@ > +#ifndef _NFT_RT_H_ > +#define _NFT_RT_H_ > + > +struct nft_rt { > + enum nft_rt_keys key:8; > + enum nft_registers dreg:8; > + u8 family; > +}; > + > +extern const struct nla_policy nft_rt_policy[]; > + > +int nft_rt_get_init(const struct nft_ctx *ctx, > + const struct nft_expr *expr, > + const struct nlattr * const tb[]); > + > +int nft_rt_get_dump(struct sk_buff *skb, > + const struct nft_expr *expr); > + > +void nft_rt_get_eval(const struct nft_expr *expr, > + struct nft_regs *regs, > + const struct nft_pktinfo *pkt); > + > +#endif > diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig > --- a/net/netfilter/Kconfig > +++ b/net/netfilter/Kconfig > @@ -474,6 +474,12 @@ config NFT_META > This option adds the "meta" expression that you can use to match and > to set packet metainformation such as the packet mark. > > +config NFT_RT > + tristate "Netfilter nf_tables routing module" > + help > + This option adds the "rt" expression that you can use to match > + packet routing information such as the packet nexthop. > + > config NFT_NUMGEN > tristate "Netfilter nf_tables number generator module" > help > diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile > --- a/net/netfilter/Makefile > +++ b/net/netfilter/Makefile > @@ -81,6 +81,7 @@ obj-$(CONFIG_NF_TABLES_NETDEV) += nf_tables_netdev.o > obj-$(CONFIG_NFT_COMPAT) += nft_compat.o > obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o > obj-$(CONFIG_NFT_META) += nft_meta.o > +obj-$(CONFIG_NFT_RT) += nft_rt.o > obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o > obj-$(CONFIG_NFT_CT) += nft_ct.o > obj-$(CONFIG_NFT_LIMIT) += nft_limit.o > diff --git a/net/netfilter/nft_rt.c b/net/netfilter/nft_rt.c > --- /dev/null > +++ b/net/netfilter/nft_rt.c > @@ -0,0 +1,145 @@ > +/* > + * Copyright (c) 2016 Anders K. Pedersen <akp@xxxxxxxxxxxx> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#include <linux/kernel.h> > +#include <linux/init.h> > +#include <linux/module.h> > +#include <linux/netlink.h> > +#include <linux/netfilter.h> > +#include <linux/netfilter/nf_tables.h> > +#include <net/dst.h> > +#include <net/netfilter/nf_tables.h> > +#include <net/netfilter/nf_tables_core.h> > +#include <net/netfilter/nft_rt.h> > + > +void nft_rt_get_eval(const struct nft_expr *expr, > + struct nft_regs *regs, > + const struct nft_pktinfo *pkt) > +{ > + const struct nft_rt *priv = nft_expr_priv(expr); > + const struct sk_buff *skb = pkt->skb; > + u32 *dest = ®s->data[priv->dreg]; > + > + switch (priv->key) { > +#ifdef CONFIG_IP_ROUTE_CLASSID > + case NFT_RT_CLASSID: { > + const struct dst_entry *dst = skb_dst(skb); > + > + if (dst == NULL) > + goto err; > + *dest = dst->tclassid; > + break; > + } > +#endif > + default: > + WARN_ON(1); > + goto err; > + } > + return; > + > +err: > + regs->verdict.code = NFT_BREAK; > +} > +EXPORT_SYMBOL_GPL(nft_rt_get_eval); > + > +const struct nla_policy nft_rt_policy[NFTA_RT_MAX + 1] = { > + [NFTA_RT_DREG] = { .type = NLA_U32 }, > + [NFTA_RT_KEY] = { .type = NLA_U32 }, > + [NFTA_RT_FAMILY] = { .type = NLA_U32 }, > +}; > +EXPORT_SYMBOL_GPL(nft_rt_policy); > + > +int nft_rt_get_init(const struct nft_ctx *ctx, > + const struct nft_expr *expr, > + const struct nlattr * const tb[]) > +{ > + struct nft_rt *priv = nft_expr_priv(expr); > + unsigned int len; > + > + priv->key = ntohl(nla_get_be32(tb[NFTA_RT_KEY])); > + switch (priv->key) { > +#ifdef CONFIG_IP_ROUTE_CLASSID > + case NFT_RT_CLASSID: > + len = sizeof(u32); > + break; > +#endif > + default: > + return -EOPNOTSUPP; > + } > + > + priv->family = ntohl(nla_get_be32(tb[NFTA_RT_FAMILY])); > + priv->dreg = nft_parse_register(tb[NFTA_RT_DREG]); > + return nft_validate_register_store(ctx, priv->dreg, NULL, > + NFT_DATA_VALUE, len); > +} > +EXPORT_SYMBOL_GPL(nft_rt_get_init); > + > +int nft_rt_get_dump(struct sk_buff *skb, > + const struct nft_expr *expr) > +{ > + const struct nft_rt *priv = nft_expr_priv(expr); > + > + if (nla_put_be32(skb, NFTA_RT_KEY, htonl(priv->key))) > + goto nla_put_failure; > + if (nft_dump_register(skb, NFTA_RT_DREG, priv->dreg)) > + goto nla_put_failure; > + if (nla_put_be32(skb, NFTA_RT_FAMILY, htonl(priv->family))) > + goto nla_put_failure; > + return 0; > + > +nla_put_failure: > + return -1; > +} > +EXPORT_SYMBOL_GPL(nft_rt_get_dump); > + > +static struct nft_expr_type nft_rt_type; > +static const struct nft_expr_ops nft_rt_get_ops = { > + .type = &nft_rt_type, > + .size = NFT_EXPR_SIZE(sizeof(struct nft_rt)), > + .eval = nft_rt_get_eval, > + .init = nft_rt_get_init, > + .dump = nft_rt_get_dump, > +}; > + > +static const struct nft_expr_ops * > +nft_rt_select_ops(const struct nft_ctx *ctx, > + const struct nlattr * const tb[]) > +{ > + if (tb[NFTA_RT_KEY] == NULL) > + return ERR_PTR(-EINVAL); > + > + if (tb[NFTA_RT_DREG]) > + return &nft_rt_get_ops; > + > + return ERR_PTR(-EINVAL); > +} I don't understand why you use select_ops. Do you plan to extend this expr behaviour in the near future? -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html