From: wenxu <wenxu@ucloud.cn> This series add NFT_TUNNEL_IP/6_SRC/DST match and tunnel expr offload. Also add NFTA_TUNNEL_KEY_RELEASE actions adn objref, tunnel obj offload This version just rebase to master for patch 7 wenxu (8): netfilter: nft_tunnel: add nft_tunnel_mode_validate function netfilter: nft_tunnel: support NFT_TUNNEL_IP_SRC/DST match netfilter: nft_tunnel: add ipv6 check in nft_tunnel_mode_validate netfilter: nft_tunnel: support NFT_TUNNEL_IP6_SRC/DST match netfilter: nft_tunnel: support tunnel meta match offload netfilter: nft_tunnel: add NFTA_TUNNEL_KEY_RELEASE action netfilter: nft_objref: add nft_objref_type offload netfilter: nft_tunnel: support nft_tunnel_obj offload include/net/netfilter/nf_tables.h | 4 + include/net/netfilter/nf_tables_offload.h | 5 + include/uapi/linux/netfilter/nf_tables.h | 5 + net/netfilter/nft_objref.c | 14 +++ net/netfilter/nft_tunnel.c | 159 +++++++++++++++++++++++++++--- 5 files changed, 174 insertions(+), 13 deletions(-) -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> Move mode validate common code to nft_tunnel_mode_validate function. Signed-off-by: wenxu <wenxu@ucloud.cn> --- v6: no change net/netfilter/nft_tunnel.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index 3d4c2ae..d374466 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -18,6 +18,18 @@ struct nft_tunnel { enum nft_tunnel_mode mode:8; }; +bool nft_tunnel_mode_validate(enum nft_tunnel_mode priv_mode, u8 tun_mode) +{ + if (priv_mode == NFT_TUNNEL_MODE_NONE || + (priv_mode == NFT_TUNNEL_MODE_RX && + !(tun_mode & IP_TUNNEL_INFO_TX)) || + (priv_mode == NFT_TUNNEL_MODE_TX && + (tun_mode & IP_TUNNEL_INFO_TX))) + return true; + + return false; +} + static void nft_tunnel_get_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) @@ -34,11 +46,7 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr, nft_reg_store8(dest, false); return; } - if (priv->mode == NFT_TUNNEL_MODE_NONE || - (priv->mode == NFT_TUNNEL_MODE_RX && - !(tun_info->mode & IP_TUNNEL_INFO_TX)) || - (priv->mode == NFT_TUNNEL_MODE_TX && - (tun_info->mode & IP_TUNNEL_INFO_TX))) + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) nft_reg_store8(dest, true); else nft_reg_store8(dest, false); @@ -48,11 +56,7 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr, regs->verdict.code = NFT_BREAK; return; } - if (priv->mode == NFT_TUNNEL_MODE_NONE || - (priv->mode == NFT_TUNNEL_MODE_RX && - !(tun_info->mode & IP_TUNNEL_INFO_TX)) || - (priv->mode == NFT_TUNNEL_MODE_TX && - (tun_info->mode & IP_TUNNEL_INFO_TX))) + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) *dest = ntohl(tunnel_id_to_key32(tun_info->key.tun_id)); else regs->verdict.code = NFT_BREAK; -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> Add new two NFT_TUNNEL_IP_SRC/DST match in nft_tunnel Signed-off-by: wenxu <wenxu@ucloud.cn> --- v6: no change include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nft_tunnel.c | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 0ff932d..9a48032 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -1772,6 +1772,8 @@ enum nft_tunnel_key_attributes { enum nft_tunnel_keys { NFT_TUNNEL_PATH, NFT_TUNNEL_ID, + NFT_TUNNEL_IP_SRC, + NFT_TUNNEL_IP_DST, __NFT_TUNNEL_MAX }; #define NFT_TUNNEL_MAX (__NFT_TUNNEL_MAX - 1) diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index d374466..fe544bf 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -61,6 +61,26 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr, else regs->verdict.code = NFT_BREAK; break; + case NFT_TUNNEL_IP_SRC: + if (!tun_info) { + regs->verdict.code = NFT_BREAK; + return; + } + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) + *dest = tun_info->key.u.ipv4.src; + else + regs->verdict.code = NFT_BREAK; + break; + case NFT_TUNNEL_IP_DST: + if (!tun_info) { + regs->verdict.code = NFT_BREAK; + return; + } + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) + *dest = tun_info->key.u.ipv4.dst; + else + regs->verdict.code = NFT_BREAK; + break; default: WARN_ON(1); regs->verdict.code = NFT_BREAK; @@ -90,6 +110,8 @@ static int nft_tunnel_get_init(const struct nft_ctx *ctx, len = sizeof(u8); break; case NFT_TUNNEL_ID: + case NFT_TUNNEL_IP_SRC: + case NFT_TUNNEL_IP_DST: len = sizeof(u32); break; default: -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> Add ipv6 tunnel check in nft_tunnel_mode_validate. Signed-off-by: wenxu <wenxu@ucloud.cn> --- v6: no change net/netfilter/nft_tunnel.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index fe544bf..64bda3d 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -18,8 +18,12 @@ struct nft_tunnel { enum nft_tunnel_mode mode:8; }; -bool nft_tunnel_mode_validate(enum nft_tunnel_mode priv_mode, u8 tun_mode) +bool nft_tunnel_mode_validate(enum nft_tunnel_mode priv_mode, + u8 tun_mode, bool ipv6) { + if (ipv6 && !(tun_mode & IP_TUNNEL_INFO_IPV6)) + return false; + if (priv_mode == NFT_TUNNEL_MODE_NONE || (priv_mode == NFT_TUNNEL_MODE_RX && !(tun_mode & IP_TUNNEL_INFO_TX)) || @@ -46,7 +50,7 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr, nft_reg_store8(dest, false); return; } - if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode, false)) nft_reg_store8(dest, true); else nft_reg_store8(dest, false); @@ -56,7 +60,7 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr, regs->verdict.code = NFT_BREAK; return; } - if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode, false)) *dest = ntohl(tunnel_id_to_key32(tun_info->key.tun_id)); else regs->verdict.code = NFT_BREAK; @@ -66,7 +70,7 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr, regs->verdict.code = NFT_BREAK; return; } - if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode, false)) *dest = tun_info->key.u.ipv4.src; else regs->verdict.code = NFT_BREAK; @@ -76,7 +80,7 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr, regs->verdict.code = NFT_BREAK; return; } - if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode, false)) *dest = tun_info->key.u.ipv4.dst; else regs->verdict.code = NFT_BREAK; -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> Add new two NFT_TUNNEL_IP6_SRC/DST match in nft_tunnel Signed-off-by: wenxu <wenxu@ucloud.cn> --- v6: no change include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nft_tunnel.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 9a48032..49fcb27 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -1774,6 +1774,8 @@ enum nft_tunnel_keys { NFT_TUNNEL_ID, NFT_TUNNEL_IP_SRC, NFT_TUNNEL_IP_DST, + NFT_TUNNEL_IP6_SRC, + NFT_TUNNEL_IP6_DST, __NFT_TUNNEL_MAX }; #define NFT_TUNNEL_MAX (__NFT_TUNNEL_MAX - 1) diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index 64bda3d..58b6083 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -85,6 +85,26 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr, else regs->verdict.code = NFT_BREAK; break; + case NFT_TUNNEL_IP6_SRC: + if (!tun_info) { + regs->verdict.code = NFT_BREAK; + return; + } + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode, true)) + memcpy(dest, &tun_info->key.u.ipv6.src, sizeof(struct in6_addr)); + else + regs->verdict.code = NFT_BREAK; + break; + case NFT_TUNNEL_IP6_DST: + if (!tun_info) { + regs->verdict.code = NFT_BREAK; + return; + } + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode, true)) + memcpy(dest, &tun_info->key.u.ipv6.dst, sizeof(struct in6_addr)); + else + regs->verdict.code = NFT_BREAK; + break; default: WARN_ON(1); regs->verdict.code = NFT_BREAK; @@ -118,6 +138,10 @@ static int nft_tunnel_get_init(const struct nft_ctx *ctx, case NFT_TUNNEL_IP_DST: len = sizeof(u32); break; + case NFT_TUNNEL_IP6_SRC: + case NFT_TUNNEL_IP6_DST: + len = sizeof(struct in6_addr); + break; default: return -EOPNOTSUPP; } -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> Add tunnel meta match offload. Currently support for NFT_TUNNEL_ID NFT_TUNNEL_SRC_IP and NFT_TUNNEL_DST_IP Signed-off-by: wenxu <wenxu@ucloud.cn> --- v6: no change include/net/netfilter/nf_tables_offload.h | 5 ++++ net/netfilter/nft_tunnel.c | 41 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h index db10466..3c4de94 100644 --- a/include/net/netfilter/nf_tables_offload.h +++ b/include/net/netfilter/nf_tables_offload.h @@ -44,6 +44,11 @@ struct nft_flow_key { struct flow_dissector_key_ip ip; struct flow_dissector_key_vlan vlan; struct flow_dissector_key_eth_addrs eth_addrs; + struct flow_dissector_key_keyid enc_key_id; + union { + struct flow_dissector_key_ipv4_addrs enc_ipv4; + struct flow_dissector_key_ipv6_addrs enc_ipv6; + }; } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */ struct nft_flow_match { diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index 58b6083..018ec27 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -11,6 +11,7 @@ #include <net/ip_tunnels.h> #include <net/vxlan.h> #include <net/erspan.h> +#include <net/netfilter/nf_tables_offload.h> struct nft_tunnel { enum nft_tunnel_keys key:8; @@ -177,6 +178,45 @@ static int nft_tunnel_get_dump(struct sk_buff *skb, return -1; } +static int nft_tunnel_get_offload(struct nft_offload_ctx *ctx, + struct nft_flow_rule *flow, + const struct nft_expr *expr) +{ + const struct nft_tunnel *priv = nft_expr_priv(expr); + struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; + + if (priv->mode == NFT_TUNNEL_MODE_TX) + return -EOPNOTSUPP; + + switch (priv->key) { + case NFT_TUNNEL_ID: + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ENC_KEYID, enc_key_id, keyid, + sizeof(__u32), reg); + break; + case NFT_TUNNEL_IP_SRC: + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, enc_ipv4, src, + sizeof(__u32), reg); + break; + case NFT_TUNNEL_IP_DST: + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, enc_ipv4, dst, + sizeof(__u32), reg); + break; + case NFT_TUNNEL_IP6_SRC: + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, enc_ipv6, src, + sizeof(struct in6_addr), reg); + break; + case NFT_TUNNEL_IP6_DST: + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, enc_ipv6, dst, + sizeof(struct in6_addr), reg); + break; + case NFT_TUNNEL_PATH: + default: + return -EOPNOTSUPP; + } + + return 0; +} + static struct nft_expr_type nft_tunnel_type; static const struct nft_expr_ops nft_tunnel_get_ops = { .type = &nft_tunnel_type, @@ -184,6 +224,7 @@ static int nft_tunnel_get_dump(struct sk_buff *skb, .eval = nft_tunnel_get_eval, .init = nft_tunnel_get_init, .dump = nft_tunnel_get_dump, + .offload = nft_tunnel_get_offload, }; static struct nft_expr_type nft_tunnel_type __read_mostly = { -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> Add new NFTA_TUNNEL_KEY_RELEASE action for future offload feature Signed-off-by: wenxu <wenxu@ucloud.cn> --- v6: no change include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nft_tunnel.c | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 49fcb27..7ed66fa 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -1765,6 +1765,7 @@ enum nft_tunnel_key_attributes { NFTA_TUNNEL_KEY_SPORT, NFTA_TUNNEL_KEY_DPORT, NFTA_TUNNEL_KEY_OPTS, + NFTA_TUNNEL_KEY_RELEASE, __NFTA_TUNNEL_KEY_MAX }; #define NFTA_TUNNEL_KEY_MAX (__NFTA_TUNNEL_KEY_MAX - 1) diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index 018ec27..aa3dc52 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -247,6 +247,7 @@ struct nft_tunnel_opts { struct nft_tunnel_obj { struct metadata_dst *md; struct nft_tunnel_opts opts; + bool tunnel_key_release; }; static const struct nla_policy nft_tunnel_ip_policy[NFTA_TUNNEL_KEY_IP_MAX + 1] = { @@ -431,6 +432,7 @@ static int nft_tunnel_obj_opts_init(const struct nft_ctx *ctx, [NFTA_TUNNEL_KEY_TOS] = { .type = NLA_U8, }, [NFTA_TUNNEL_KEY_TTL] = { .type = NLA_U8, }, [NFTA_TUNNEL_KEY_OPTS] = { .type = NLA_NESTED, }, + [NFTA_TUNNEL_KEY_RELEASE] = { .type = NLA_U8, }, }; static int nft_tunnel_obj_init(const struct nft_ctx *ctx, @@ -442,6 +444,12 @@ static int nft_tunnel_obj_init(const struct nft_ctx *ctx, struct metadata_dst *md; int err; + if (tb[NFTA_TUNNEL_KEY_RELEASE]) { + priv->tunnel_key_release = !!nla_get_u8(tb[NFTA_TUNNEL_KEY_RELEASE]); + if (priv->tunnel_key_release) + return 0; + } + if (!tb[NFTA_TUNNEL_KEY_ID]) return -EINVAL; @@ -524,8 +532,11 @@ static inline void nft_tunnel_obj_eval(struct nft_object *obj, struct sk_buff *skb = pkt->skb; skb_dst_drop(skb); - dst_hold((struct dst_entry *) priv->md); - skb_dst_set(skb, (struct dst_entry *) priv->md); + + if (!priv->tunnel_key_release) { + dst_hold((struct dst_entry *)priv->md); + skb_dst_set(skb, (struct dst_entry *)priv->md); + } } static int nft_tunnel_ip_dump(struct sk_buff *skb, struct ip_tunnel_info *info) @@ -627,6 +638,12 @@ static int nft_tunnel_obj_dump(struct sk_buff *skb, struct nft_tunnel_obj *priv = nft_obj_data(obj); struct ip_tunnel_info *info = &priv->md->u.tun_info; + if (priv->tunnel_key_release) { + if (nla_put_u8(skb, NFTA_TUNNEL_KEY_RELEASE, 1)) + goto nla_put_failure; + return 0; + } + if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ID, tunnel_id_to_key32(info->key.tun_id)) || nft_tunnel_ip_dump(skb, info) < 0 || @@ -648,7 +665,8 @@ static void nft_tunnel_obj_destroy(const struct nft_ctx *ctx, { struct nft_tunnel_obj *priv = nft_obj_data(obj); - metadata_dst_free(priv->md); + if (!priv->tunnel_key_release) + metadata_dst_free(priv->md); } static struct nft_object_type nft_tunnel_obj_type; -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> support offload for nft_objref_type Signed-off-by: wenxu <wenxu@ucloud.cn> --- v6: rebase to the master include/net/netfilter/nf_tables.h | 4 ++++ net/netfilter/nft_objref.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 3d9e66a..498f662 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -1128,6 +1128,7 @@ struct nft_object_type { * @destroy: release existing stateful object * @dump: netlink dump stateful object * @update: update stateful object + * @update: offload stateful object */ struct nft_object_ops { void (*eval)(struct nft_object *obj, @@ -1144,6 +1145,9 @@ struct nft_object_ops { bool reset); void (*update)(struct nft_object *obj, struct nft_object *newobj); + int (*offload)(struct nft_offload_ctx *ctx, + struct nft_flow_rule *flow, + struct nft_object *obj); const struct nft_object_type *type; }; diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c index bfd18d2..4a70972 100644 --- a/net/netfilter/nft_objref.c +++ b/net/netfilter/nft_objref.c @@ -10,6 +10,7 @@ #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h> +#include <net/netfilter/nf_tables_offload.h> #define nft_objref_priv(expr) *((struct nft_object **)nft_expr_priv(expr)) @@ -82,6 +83,18 @@ static void nft_objref_activate(const struct nft_ctx *ctx, obj->use++; } +static int nft_objref_offload(struct nft_offload_ctx *ctx, + struct nft_flow_rule *flow, + const struct nft_expr *expr) +{ + struct nft_object *obj = nft_objref_priv(expr); + + if (obj->ops->offload) + return obj->ops->offload(ctx, flow, obj); + else + return -EOPNOTSUPP; +} + static struct nft_expr_type nft_objref_type; static const struct nft_expr_ops nft_objref_ops = { .type = &nft_objref_type, @@ -91,6 +104,7 @@ static void nft_objref_activate(const struct nft_ctx *ctx, .activate = nft_objref_activate, .deactivate = nft_objref_deactivate, .dump = nft_objref_dump, + .offload = nft_objref_offload, }; struct nft_objref_map { -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> Add nft_tunnel_obj offload for both encap and decap actions Signed-off-by: wenxu <wenxu@ucloud.cn> --- v6: no change net/netfilter/nft_tunnel.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index aa3dc52..b47838d 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -669,6 +669,25 @@ static void nft_tunnel_obj_destroy(const struct nft_ctx *ctx, metadata_dst_free(priv->md); } +static int nft_tunnel_obj_offload(struct nft_offload_ctx *ctx, + struct nft_flow_rule *flow, + struct nft_object *obj) +{ + struct nft_tunnel_obj *priv = nft_obj_data(obj); + struct flow_action_entry *entry; + + entry = &flow->rule->action.entries[ctx->num_actions++]; + + if (!priv->tunnel_key_release) { + entry->id = FLOW_ACTION_TUNNEL_ENCAP; + entry->tunnel = &priv->md->u.tun_info; + } else { + entry->id = FLOW_ACTION_TUNNEL_DECAP; + } + + return 0; +} + static struct nft_object_type nft_tunnel_obj_type; static const struct nft_object_ops nft_tunnel_obj_ops = { .type = &nft_tunnel_obj_type, @@ -677,6 +696,7 @@ static void nft_tunnel_obj_destroy(const struct nft_ctx *ctx, .init = nft_tunnel_obj_init, .destroy = nft_tunnel_obj_destroy, .dump = nft_tunnel_obj_dump, + .offload = nft_tunnel_obj_offload, }; static struct nft_object_type nft_tunnel_obj_type __read_mostly = { -- 1.8.3.1
Only one series at a time, sorry.
On Sun, Sep 08, 2019 at 10:22:00PM +0800, wenxu@ucloud.cn wrote:
> From: wenxu <wenxu@ucloud.cn>
>
> This series add NFT_TUNNEL_IP/6_SRC/DST match and tunnel expr offload.
> Also add NFTA_TUNNEL_KEY_RELEASE actions adn objref, tunnel obj offload
>
> This version just rebase to master for patch 7
>
> wenxu (8):
> netfilter: nft_tunnel: add nft_tunnel_mode_validate function
> netfilter: nft_tunnel: support NFT_TUNNEL_IP_SRC/DST match
> netfilter: nft_tunnel: add ipv6 check in nft_tunnel_mode_validate
> netfilter: nft_tunnel: support NFT_TUNNEL_IP6_SRC/DST match
> netfilter: nft_tunnel: support tunnel meta match offload
> netfilter: nft_tunnel: add NFTA_TUNNEL_KEY_RELEASE action
> netfilter: nft_objref: add nft_objref_type offload
> netfilter: nft_tunnel: support nft_tunnel_obj offload
>
> include/net/netfilter/nf_tables.h | 4 +
> include/net/netfilter/nf_tables_offload.h | 5 +
> include/uapi/linux/netfilter/nf_tables.h | 5 +
> net/netfilter/nft_objref.c | 14 +++
> net/netfilter/nft_tunnel.c | 159 +++++++++++++++++++++++++++---
> 5 files changed, 174 insertions(+), 13 deletions(-)
>
> --
> 1.8.3.1
>
From: wenxu <wenxu@ucloud.cn> Add new NFTA_TUNNEL_KEY_RELEASE action for future offload feature Signed-off-by: wenxu <wenxu@ucloud.cn> --- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nft_tunnel.c | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index da9b1d1..0e24c27 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -1766,6 +1766,7 @@ enum nft_tunnel_key_attributes { NFTA_TUNNEL_KEY_SPORT, NFTA_TUNNEL_KEY_DPORT, NFTA_TUNNEL_KEY_OPTS, + NFTA_TUNNEL_KEY_RELEASE, __NFTA_TUNNEL_KEY_MAX }; #define NFTA_TUNNEL_KEY_MAX (__NFTA_TUNNEL_KEY_MAX - 1) diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index 68ca894..15d5dc9 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -262,6 +262,7 @@ struct nft_tunnel_opts { struct nft_tunnel_obj { struct metadata_dst *md; struct nft_tunnel_opts opts; + bool tunnel_key_release; }; static const struct nla_policy nft_tunnel_ip_policy[NFTA_TUNNEL_KEY_IP_MAX + 1] = { @@ -446,6 +447,7 @@ static int nft_tunnel_obj_opts_init(const struct nft_ctx *ctx, [NFTA_TUNNEL_KEY_TOS] = { .type = NLA_U8, }, [NFTA_TUNNEL_KEY_TTL] = { .type = NLA_U8, }, [NFTA_TUNNEL_KEY_OPTS] = { .type = NLA_NESTED, }, + [NFTA_TUNNEL_KEY_RELEASE] = { .type = NLA_U8, }, }; static int nft_tunnel_obj_init(const struct nft_ctx *ctx, @@ -457,6 +459,12 @@ static int nft_tunnel_obj_init(const struct nft_ctx *ctx, struct metadata_dst *md; int err; + if (tb[NFTA_TUNNEL_KEY_RELEASE] && + nla_get_u8(tb[NFTA_TUNNEL_KEY_RELEASE])) { + priv->tunnel_key_release = true; + return 0; + } + if (!tb[NFTA_TUNNEL_KEY_ID]) return -EINVAL; @@ -539,8 +547,11 @@ static inline void nft_tunnel_obj_eval(struct nft_object *obj, struct sk_buff *skb = pkt->skb; skb_dst_drop(skb); - dst_hold((struct dst_entry *) priv->md); - skb_dst_set(skb, (struct dst_entry *) priv->md); + + if (!priv->tunnel_key_release) { + dst_hold((struct dst_entry *)priv->md); + skb_dst_set(skb, (struct dst_entry *)priv->md); + } } static int nft_tunnel_ip_dump(struct sk_buff *skb, struct ip_tunnel_info *info) @@ -642,6 +653,12 @@ static int nft_tunnel_obj_dump(struct sk_buff *skb, struct nft_tunnel_obj *priv = nft_obj_data(obj); struct ip_tunnel_info *info = &priv->md->u.tun_info; + if (priv->tunnel_key_release) { + if (nla_put_u8(skb, NFTA_TUNNEL_KEY_RELEASE, 1)) + goto nla_put_failure; + return 0; + } + if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ID, tunnel_id_to_key32(info->key.tun_id)) || nft_tunnel_ip_dump(skb, info) < 0 || @@ -663,7 +680,8 @@ static void nft_tunnel_obj_destroy(const struct nft_ctx *ctx, { struct nft_tunnel_obj *priv = nft_obj_data(obj); - metadata_dst_free(priv->md); + if (!priv->tunnel_key_release) + metadata_dst_free(priv->md); } static struct nft_object_type nft_tunnel_obj_type; -- 1.8.3.1