From: wenxu <wenxu@ucloud.cn> This series patch support more expr and obj offload: fw_nedev, set payload, tunnel encap/decap action, tunnel meta match, objref offload The follwing is the test sample: # nft add table netdev firewall # nft add tunnel netdev firewall encap tunid 1000 tundst 0xf198a8ac tunsrc 0x4b98a8ac tunrelease 0 # nft add tunnel netdev firewall decap tunid 0 tundst 0 tunsrc 0 tunrelease 1 # nft add chain netdev firewall aclout { type filter hook ingress device mlx_pf0vf0 priority - 300 \; } # nft --debug=netlink add rule netdev firewall aclout ip daddr 10.0.1.7 @ll,0,48 set 0x00002e9ca06e2596 @ll,48,48 set 0xfaffffffffff tunnel name encap fwd to gretap [ meta load protocol => reg 1 ] [ cmp eq reg 1 0x00000008 ] [ payload load 4b @ network header + 16 => reg 1 ] [ cmp eq reg 1 0x0701000a ] [ immediate reg 1 0x6ea09c2e 0x00009625 ] [ payload write reg 1 => 6b @ link header + 0 csum_type 0 csum_off 0 csum_flags 0x0 ] [ immediate reg 1 0xfffffffa 0x0000ffff ] [ payload write reg 1 => 6b @ link header + 6 csum_type 0 csum_off 0 csum_flags 0x0 ] [ objref type 6 name encap ] [ immediate reg 1 0x00000019 ] [ fwd sreg_dev 1 ] # nft add chain netdev firewall aclin { type filter hook ingress device gretap priority - 300 \; } # nft --debug=netlink add rule netdev firewall aclin ip daddr 10.0.0.7 tunnel tunid 1000 tunnel tundst 172.168.152.75 tunnel tunsrc 172.168.152.241 tunnel name decap @ll,0,48 set 0x0000525400001275 @ll,48,48 set 0xfaffffffffff fwd to mlx_pf0vf0 [ meta load protocol => reg 1 ] [ cmp eq reg 1 0x00000008 ] [ payload load 4b @ network header + 16 => reg 1 ] [ cmp eq reg 1 0x0700000a ] [ tunnel load id => reg 1 ] [ cmp eq reg 1 0x000003e8 ] [ tunnel load tun_dst => reg 1 ] [ cmp eq reg 1 0xaca8984b ] [ tunnel load tun_src => reg 1 ] [ cmp eq reg 1 0xaca898f1 ] [ objref type 6 name decap ] [ immediate reg 1 0x00005452 0x00007512 ] [ payload write reg 1 => 6b @ link header + 0 csum_type 0 csum_off 0 csum_flags 0x0 ] [ immediate reg 1 0xfffffffa 0x0000ffff ] [ payload write reg 1 => 6b @ link header + 6 csum_type 0 csum_off 0 csum_flags 0x0 ] [ immediate reg 1 0x0000000f ] [ fwd sreg_dev 1 ] wenxu (9): netfilter: nf_flow_offload: add net in offload_ctx netfilter: nf_tables_offload: add offload_actions callback netfilter: nft_fwd_netdev: add fw_netdev action support netfilter: nft_payload: add nft_set_payload offload support netfilter: nft_tunnel: support NFT_TUNNEL_SRC/DST_IP 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 | 10 ++- include/net/netfilter/nf_tables_offload.h | 7 +- include/uapi/linux/netfilter/nf_tables.h | 3 + net/netfilter/nf_tables_api.c | 2 +- net/netfilter/nf_tables_offload.c | 7 +- net/netfilter/nft_fwd_netdev.c | 27 +++++++ net/netfilter/nft_immediate.c | 2 +- net/netfilter/nft_objref.c | 15 ++++ net/netfilter/nft_payload.c | 56 ++++++++++++++ net/netfilter/nft_tunnel.c | 123 ++++++++++++++++++++++++++---- 10 files changed, 230 insertions(+), 22 deletions(-) -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> In the offload_ctx, the net can be used for other actions such as fwd netdev Signed-off-by: wenxu <wenxu@ucloud.cn> --- v3: no change include/net/netfilter/nf_tables_offload.h | 3 ++- net/netfilter/nf_tables_api.c | 2 +- net/netfilter/nf_tables_offload.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h index 3196663..ad61958 100644 --- a/include/net/netfilter/nf_tables_offload.h +++ b/include/net/netfilter/nf_tables_offload.h @@ -24,6 +24,7 @@ struct nft_offload_ctx { __be16 l3num; u8 protonum; } dep; + struct net *net; unsigned int num_actions; struct nft_offload_reg regs[NFT_REG32_15 + 1]; }; @@ -60,7 +61,7 @@ struct nft_flow_rule { #define NFT_OFFLOAD_F_ACTION (1 << 0) struct nft_rule; -struct nft_flow_rule *nft_flow_rule_create(const struct nft_rule *rule); +struct nft_flow_rule *nft_flow_rule_create(struct net *net, const struct nft_rule *rule); void nft_flow_rule_destroy(struct nft_flow_rule *flow); int nft_flow_rule_offload_commit(struct net *net); diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 605a7cf..c6dc173 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -2844,7 +2844,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, return nft_table_validate(net, table); if (chain->flags & NFT_CHAIN_HW_OFFLOAD) { - flow = nft_flow_rule_create(rule); + flow = nft_flow_rule_create(net, rule); if (IS_ERR(flow)) return PTR_ERR(flow); diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c index 64f5fd5..5c1fef7 100644 --- a/net/netfilter/nf_tables_offload.c +++ b/net/netfilter/nf_tables_offload.c @@ -28,12 +28,13 @@ static struct nft_flow_rule *nft_flow_rule_alloc(int num_actions) return flow; } -struct nft_flow_rule *nft_flow_rule_create(const struct nft_rule *rule) +struct nft_flow_rule *nft_flow_rule_create(struct net *net, const struct nft_rule *rule) { struct nft_offload_ctx ctx = { .dep = { .type = NFT_OFFLOAD_DEP_UNSPEC, }, + .net = net, }; struct nft_flow_rule *flow; int num_actions = 0, err; -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> There will be zero one or serval actions for some expr. such as payload set and immediate. The one payload set action maybe split to several offload entries. And only NFT_REG_VERDICT immediate action has 1 offload entry Signed-off-by: wenxu <wenxu@ucloud.cn> --- v3: no change include/net/netfilter/nf_tables.h | 7 ++++++- include/net/netfilter/nf_tables_offload.h | 2 -- net/netfilter/nf_tables_offload.c | 4 ++-- net/netfilter/nft_immediate.c | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 9b62456..9285df2 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -785,7 +785,7 @@ struct nft_expr_ops { int (*offload)(struct nft_offload_ctx *ctx, struct nft_flow_rule *flow, const struct nft_expr *expr); - u32 offload_flags; + int (*offload_actions)(const struct nft_expr *expr); const struct nft_expr_type *type; void *data; }; @@ -794,6 +794,11 @@ struct nft_expr_ops { #define NFT_EXPR_SIZE(size) (sizeof(struct nft_expr) + \ ALIGN(size, __alignof__(struct nft_expr))) +static inline int nft_offload_action(const struct nft_expr *expr) +{ + return 1; +} + /** * struct nft_expr - nf_tables expression * diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h index ad61958..275d014 100644 --- a/include/net/netfilter/nf_tables_offload.h +++ b/include/net/netfilter/nf_tables_offload.h @@ -58,8 +58,6 @@ struct nft_flow_rule { struct flow_rule *rule; }; -#define NFT_OFFLOAD_F_ACTION (1 << 0) - struct nft_rule; struct nft_flow_rule *nft_flow_rule_create(struct net *net, const struct nft_rule *rule); void nft_flow_rule_destroy(struct nft_flow_rule *flow); diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c index 5c1fef7..33543f5 100644 --- a/net/netfilter/nf_tables_offload.c +++ b/net/netfilter/nf_tables_offload.c @@ -42,8 +42,8 @@ struct nft_flow_rule *nft_flow_rule_create(struct net *net, const struct nft_rul expr = nft_expr_first(rule); while (expr->ops && expr != nft_expr_last(rule)) { - if (expr->ops->offload_flags & NFT_OFFLOAD_F_ACTION) - num_actions++; + if (expr->ops->offload_actions) + num_actions += expr->ops->offload_actions(expr); expr = nft_expr_next(expr); } diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c index ca2ae4b..391f699 100644 --- a/net/netfilter/nft_immediate.c +++ b/net/netfilter/nft_immediate.c @@ -163,7 +163,7 @@ static int nft_immediate_offload(struct nft_offload_ctx *ctx, .dump = nft_immediate_dump, .validate = nft_immediate_validate, .offload = nft_immediate_offload, - .offload_flags = NFT_OFFLOAD_F_ACTION, + .offload_actions = nft_offload_action, }; struct nft_expr_type nft_imm_type __read_mostly = { -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> fwd_netdev action offload: nft --debug=netlink add rule netdev firewall aclout ip daddr 10.0.1.7 fwd to eth0 Signed-off-by: wenxu <wenxu@ucloud.cn> --- v3: data from source register net/netfilter/nft_fwd_netdev.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c index 61b7f93..c5af66b 100644 --- a/net/netfilter/nft_fwd_netdev.c +++ b/net/netfilter/nft_fwd_netdev.c @@ -15,6 +15,7 @@ #include <net/netfilter/nf_dup_netdev.h> #include <net/neighbour.h> #include <net/ip.h> +#include <net/netfilter/nf_tables_offload.h> struct nft_fwd_netdev { enum nft_registers sreg_dev:8; @@ -63,6 +64,30 @@ static int nft_fwd_netdev_dump(struct sk_buff *skb, const struct nft_expr *expr) return -1; } +static int nft_fwd_netdev_offload(struct nft_offload_ctx *ctx, + struct nft_flow_rule *flow, + const struct nft_expr *expr) +{ + const struct nft_fwd_netdev *priv = nft_expr_priv(expr); + struct nft_offload_reg *reg = &ctx->regs[priv->sreg_dev]; + const struct nft_data *data = ®->data; + struct flow_action_entry *entry; + struct net_device *dev; + int oif = -1; + + entry = &flow->rule->action.entries[ctx->num_actions++]; + + memcpy(&oif, data->data, sizeof(oif)); + dev = __dev_get_by_index(ctx->net, oif); + if (!dev) + return -EOPNOTSUPP; + + entry->id = FLOW_ACTION_REDIRECT; + entry->dev = dev; + + return 0; +} + struct nft_fwd_neigh { enum nft_registers sreg_dev:8; enum nft_registers sreg_addr:8; @@ -194,6 +219,8 @@ static int nft_fwd_neigh_dump(struct sk_buff *skb, const struct nft_expr *expr) .eval = nft_fwd_netdev_eval, .init = nft_fwd_netdev_init, .dump = nft_fwd_netdev_dump, + .offload = nft_fwd_netdev_offload, + .offload_actions = nft_offload_action, }; static const struct nft_expr_ops * -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> currently payload set only support ll header nft --debug=netlink add rule netdev firewall aclout ip daddr 10.0.1.7 @ll,0,48 set 0x00002e9ca06e2596 @ll,48,48 set 0xfaffffffffff fwd to eth0 Signed-off-by: wenxu <wenxu@ucloud.cn> --- v3: data from source register net/netfilter/nft_payload.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 22a80eb..980e4a1 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -562,12 +562,68 @@ static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr *expr return -1; } +static int nft_payload_set_offload(struct nft_offload_ctx *ctx, + struct nft_flow_rule *flow, + const struct nft_expr *expr) +{ + const struct nft_payload_set *priv = nft_expr_priv(expr); + struct nft_offload_reg *reg = &ctx->regs[priv->sreg]; + const struct nft_data *data = ®->data; + struct flow_action_entry *entry; + u32 len = priv->len; + u32 offset, last; + int n_actions, i; + + if (priv->base != NFT_PAYLOAD_LL_HEADER || len > 16) + return -EOPNOTSUPP; + + offset = priv->offset; + n_actions = len >> 2; + last = len & 0x3; + + for (i = 0; i < n_actions; i++) { + entry = &flow->rule->action.entries[ctx->num_actions++]; + + entry->id = FLOW_ACTION_MANGLE; + entry->mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH; + entry->mangle.mask = 0; + entry->mangle.val = data->data[i]; + entry->mangle.offset = offset; + offset = offset + 4; + } + + if (last) { + entry = &flow->rule->action.entries[ctx->num_actions++]; + + entry->id = FLOW_ACTION_MANGLE; + entry->mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH; + entry->mangle.mask = ~((1 << (last * 8)) - 1); + entry->mangle.val = data->data[i]; + entry->mangle.offset = offset; + } + + return 0; +} + +static int nft_payload_set_offload_actions(const struct nft_expr *expr) +{ + const struct nft_payload_set *priv = nft_expr_priv(expr); + u32 len = priv->len; + + if (priv->base != NFT_PAYLOAD_LL_HEADER || len > 16) + return 0; + + return (len >> 2) + !!(len & 3); +} + static const struct nft_expr_ops nft_payload_set_ops = { .type = &nft_payload_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_payload_set)), .eval = nft_payload_set_eval, .init = nft_payload_set_init, .dump = nft_payload_set_dump, + .offload = nft_payload_set_offload, + .offload_actions = nft_payload_set_offload_actions, }; static const struct nft_expr_ops * -- 1.8.3.1
From: wenxu <wenxu@ucloud.cn> Add new two NFT_TUNNEL_SRC/DST_IP match in nft_tunnel Signed-off-by: wenxu <wenxu@ucloud.cn> --- v3: no change include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nft_tunnel.c | 46 +++++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 82abaa1..173690a 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -1765,6 +1765,8 @@ enum nft_tunnel_key_attributes { enum nft_tunnel_keys { NFT_TUNNEL_PATH, NFT_TUNNEL_ID, + NFT_TUNNEL_SRC_IP, + NFT_TUNNEL_DST_IP, __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 3d4c2ae..e218163 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,15 +56,31 @@ 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; break; + case NFT_TUNNEL_SRC_IP: + if (!tun_info) { + regs->verdict.code = NFT_BREAK; + return; + } + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) + *dest = ntohl(tun_info->key.u.ipv4.src); + else + regs->verdict.code = NFT_BREAK; + break; + case NFT_TUNNEL_DST_IP: + if (!tun_info) { + regs->verdict.code = NFT_BREAK; + return; + } + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) + *dest = ntohl(tun_info->key.u.ipv4.dst); + else + regs->verdict.code = NFT_BREAK; + break; default: WARN_ON(1); regs->verdict.code = NFT_BREAK; @@ -86,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_SRC_IP: + case NFT_TUNNEL_DST_IP: len = sizeof(u32); break; default: -- 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> --- v3: set data on dest include/net/netfilter/nf_tables_offload.h | 2 ++ net/netfilter/nft_tunnel.c | 33 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h index 275d014..df76981 100644 --- a/include/net/netfilter/nf_tables_offload.h +++ b/include/net/netfilter/nf_tables_offload.h @@ -44,6 +44,8 @@ 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; + struct flow_dissector_key_ipv4_addrs enc_ipv4; } __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 e218163..f0190bc 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; @@ -149,6 +150,37 @@ 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_SRC_IP: + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, enc_ipv4, src, + sizeof(__u32), reg); + break; + case NFT_TUNNEL_DST_IP: + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, enc_ipv4, dst, + sizeof(__u32), 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, @@ -156,6 +188,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> --- v3: 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 173690a..4489b66 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -1758,6 +1758,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 f0190bc..078dcee 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -211,6 +211,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] = { @@ -395,6 +396,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, @@ -406,6 +408,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; @@ -488,8 +496,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) @@ -591,6 +602,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 || @@ -612,7 +629,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> --- v3: no change include/net/netfilter/nf_tables.h | 3 +++ net/netfilter/nft_objref.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 9285df2..d6f96c0 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -1122,6 +1122,9 @@ struct nft_object_ops { int (*dump)(struct sk_buff *skb, struct nft_object *obj, bool reset); + 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..f71cf76 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,8 @@ 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, + .offload_actions = nft_offload_action, }; 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> --- v3: 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 078dcee..8b232b0 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -633,6 +633,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, @@ -641,6 +660,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
[-- Attachment #1: Type: text/plain, Size: 1904 bytes --] Hi, Thank you for the patch! Yet something to improve: [auto build test ERROR on nf-next/master] url: https://github.com/0day-ci/linux/commits/wenxu-ucloud-cn/netfilter-nf_tables_offload-support-more-expr-and-obj-offload/20190804-144846 base: https://kernel.googlesource.com/pub/scm/linux/kernel/git/pablo/nf-next.git master config: x86_64-allyesconfig (attached as .config) compiler: gcc-7 (Debian 7.4.0-10) 7.4.0 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 If you fix the issue, kindly add following tag Reported-by: kbuild test robot <lkp@intel.com> All errors (new ones prefixed by >>): net/netfilter/nft_fwd_netdev.c: In function 'nft_fwd_netdev_offload': >> net/netfilter/nft_fwd_netdev.c:73:36: error: 'struct nft_offload_reg' has no member named 'data' const struct nft_data *data = ®->data; ^~ vim +73 net/netfilter/nft_fwd_netdev.c 66 67 static int nft_fwd_netdev_offload(struct nft_offload_ctx *ctx, 68 struct nft_flow_rule *flow, 69 const struct nft_expr *expr) 70 { 71 const struct nft_fwd_netdev *priv = nft_expr_priv(expr); 72 struct nft_offload_reg *reg = &ctx->regs[priv->sreg_dev]; > 73 const struct nft_data *data = ®->data; 74 struct flow_action_entry *entry; 75 struct net_device *dev; 76 int oif = -1; 77 78 entry = &flow->rule->action.entries[ctx->num_actions++]; 79 80 memcpy(&oif, data->data, sizeof(oif)); 81 dev = __dev_get_by_index(ctx->net, oif); 82 if (!dev) 83 return -EOPNOTSUPP; 84 85 entry->id = FLOW_ACTION_REDIRECT; 86 entry->dev = dev; 87 88 return 0; 89 } 90 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 69578 bytes --]
[-- Attachment #1: Type: text/plain, Size: 2550 bytes --] Hi, Thank you for the patch! Yet something to improve: [auto build test ERROR on nf-next/master] url: https://github.com/0day-ci/linux/commits/wenxu-ucloud-cn/netfilter-nf_tables_offload-support-more-expr-and-obj-offload/20190804-144846 base: https://kernel.googlesource.com/pub/scm/linux/kernel/git/pablo/nf-next.git master config: x86_64-rhel (attached as .config) compiler: gcc-7 (Debian 7.4.0-10) 7.4.0 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 If you fix the issue, kindly add following tag Reported-by: kbuild test robot <lkp@intel.com> All errors (new ones prefixed by >>): net//netfilter/nft_payload.c: In function 'nft_payload_set_offload': >> net//netfilter/nft_payload.c:571:36: error: 'struct nft_offload_reg' has no member named 'data' const struct nft_data *data = ®->data; ^~ vim +571 net//netfilter/nft_payload.c 564 565 static int nft_payload_set_offload(struct nft_offload_ctx *ctx, 566 struct nft_flow_rule *flow, 567 const struct nft_expr *expr) 568 { 569 const struct nft_payload_set *priv = nft_expr_priv(expr); 570 struct nft_offload_reg *reg = &ctx->regs[priv->sreg]; > 571 const struct nft_data *data = ®->data; 572 struct flow_action_entry *entry; 573 u32 len = priv->len; 574 u32 offset, last; 575 int n_actions, i; 576 577 if (priv->base != NFT_PAYLOAD_LL_HEADER || len > 16) 578 return -EOPNOTSUPP; 579 580 offset = priv->offset; 581 n_actions = len >> 2; 582 last = len & 0x3; 583 584 for (i = 0; i < n_actions; i++) { 585 entry = &flow->rule->action.entries[ctx->num_actions++]; 586 587 entry->id = FLOW_ACTION_MANGLE; 588 entry->mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH; 589 entry->mangle.mask = 0; 590 entry->mangle.val = data->data[i]; 591 entry->mangle.offset = offset; 592 offset = offset + 4; 593 } 594 595 if (last) { 596 entry = &flow->rule->action.entries[ctx->num_actions++]; 597 598 entry->id = FLOW_ACTION_MANGLE; 599 entry->mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH; 600 entry->mangle.mask = ~((1 << (last * 8)) - 1); 601 entry->mangle.val = data->data[i]; 602 entry->mangle.offset = offset; 603 } 604 605 return 0; 606 } 607 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 43535 bytes --]
This patch is no this problem. Because it is based on http://patchwork.ozlabs.org/patch/1140431/ On 8/7/2019 8:15 PM, kbuild test robot wrote: > Hi, > > Thank you for the patch! Yet something to improve: > > [auto build test ERROR on nf-next/master] > > url: https://github.com/0day-ci/linux/commits/wenxu-ucloud-cn/netfilter-nf_tables_offload-support-more-expr-and-obj-offload/20190804-144846 > base: https://kernel.googlesource.com/pub/scm/linux/kernel/git/pablo/nf-next.git master > config: x86_64-allyesconfig (attached as .config) > compiler: gcc-7 (Debian 7.4.0-10) 7.4.0 > reproduce: > # save the attached .config to linux build tree > make ARCH=x86_64 > > If you fix the issue, kindly add following tag > Reported-by: kbuild test robot <lkp@intel.com> > > All errors (new ones prefixed by >>): > > net/netfilter/nft_fwd_netdev.c: In function 'nft_fwd_netdev_offload': >>> net/netfilter/nft_fwd_netdev.c:73:36: error: 'struct nft_offload_reg' has no member named 'data' > const struct nft_data *data = ®->data; > ^~ > > vim +73 net/netfilter/nft_fwd_netdev.c > > 66 > 67 static int nft_fwd_netdev_offload(struct nft_offload_ctx *ctx, > 68 struct nft_flow_rule *flow, > 69 const struct nft_expr *expr) > 70 { > 71 const struct nft_fwd_netdev *priv = nft_expr_priv(expr); > 72 struct nft_offload_reg *reg = &ctx->regs[priv->sreg_dev]; > > 73 const struct nft_data *data = ®->data; > 74 struct flow_action_entry *entry; > 75 struct net_device *dev; > 76 int oif = -1; > 77 > 78 entry = &flow->rule->action.entries[ctx->num_actions++]; > 79 > 80 memcpy(&oif, data->data, sizeof(oif)); > 81 dev = __dev_get_by_index(ctx->net, oif); > 82 if (!dev) > 83 return -EOPNOTSUPP; > 84 > 85 entry->id = FLOW_ACTION_REDIRECT; > 86 entry->dev = dev; > 87 > 88 return 0; > 89 } > 90 > > --- > 0-DAY kernel test infrastructure Open Source Technology Center > https://lists.01.org/pipermail/kbuild-all Intel Corporation
This patch is also no this problem. Because it is based on http://patchwork.ozlabs.org/patch/1140431/ On 8/7/2019 8:18 PM, kbuild test robot wrote: > Hi, > > Thank you for the patch! Yet something to improve: > > [auto build test ERROR on nf-next/master] > > url: https://github.com/0day-ci/linux/commits/wenxu-ucloud-cn/netfilter-nf_tables_offload-support-more-expr-and-obj-offload/20190804-144846 > base: https://kernel.googlesource.com/pub/scm/linux/kernel/git/pablo/nf-next.git master > config: x86_64-rhel (attached as .config) > compiler: gcc-7 (Debian 7.4.0-10) 7.4.0 > reproduce: > # save the attached .config to linux build tree > make ARCH=x86_64 > > If you fix the issue, kindly add following tag > Reported-by: kbuild test robot <lkp@intel.com> > > All errors (new ones prefixed by >>): > > net//netfilter/nft_payload.c: In function 'nft_payload_set_offload': >>> net//netfilter/nft_payload.c:571:36: error: 'struct nft_offload_reg' has no member named 'data' > const struct nft_data *data = ®->data; > ^~ > > vim +571 net//netfilter/nft_payload.c > > 564 > 565 static int nft_payload_set_offload(struct nft_offload_ctx *ctx, > 566 struct nft_flow_rule *flow, > 567 const struct nft_expr *expr) > 568 { > 569 const struct nft_payload_set *priv = nft_expr_priv(expr); > 570 struct nft_offload_reg *reg = &ctx->regs[priv->sreg]; > > 571 const struct nft_data *data = ®->data; > 572 struct flow_action_entry *entry; > 573 u32 len = priv->len; > 574 u32 offset, last; > 575 int n_actions, i; > 576 > 577 if (priv->base != NFT_PAYLOAD_LL_HEADER || len > 16) > 578 return -EOPNOTSUPP; > 579 > 580 offset = priv->offset; > 581 n_actions = len >> 2; > 582 last = len & 0x3; > 583 > 584 for (i = 0; i < n_actions; i++) { > 585 entry = &flow->rule->action.entries[ctx->num_actions++]; > 586 > 587 entry->id = FLOW_ACTION_MANGLE; > 588 entry->mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH; > 589 entry->mangle.mask = 0; > 590 entry->mangle.val = data->data[i]; > 591 entry->mangle.offset = offset; > 592 offset = offset + 4; > 593 } > 594 > 595 if (last) { > 596 entry = &flow->rule->action.entries[ctx->num_actions++]; > 597 > 598 entry->id = FLOW_ACTION_MANGLE; > 599 entry->mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH; > 600 entry->mangle.mask = ~((1 << (last * 8)) - 1); > 601 entry->mangle.val = data->data[i]; > 602 entry->mangle.offset = offset; > 603 } > 604 > 605 return 0; > 606 } > 607 > > --- > 0-DAY kernel test infrastructure Open Source Technology Center > https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi pablo,
How about also for this series?
On 8/1/2019 10:01 PM, wenxu@ucloud.cn wrote:
> From: wenxu <wenxu@ucloud.cn>
>
> This series patch support more expr and obj offload:
> fw_nedev, set payload, tunnel encap/decap action,
> tunnel meta match, objref offload
>
> The follwing is the test sample:
>
> # nft add table netdev firewall
> # nft add tunnel netdev firewall encap tunid 1000 tundst 0xf198a8ac tunsrc 0x4b98a8ac tunrelease 0
> # nft add tunnel netdev firewall decap tunid 0 tundst 0 tunsrc 0 tunrelease 1
> # nft add chain netdev firewall aclout { type filter hook ingress device mlx_pf0vf0 priority - 300 \; }
> # nft --debug=netlink add rule netdev firewall aclout ip daddr 10.0.1.7 @ll,0,48 set 0x00002e9ca06e2596 @ll,48,48 set 0xfaffffffffff tunnel name encap fwd to gretap
> [ meta load protocol => reg 1 ]
> [ cmp eq reg 1 0x00000008 ]
> [ payload load 4b @ network header + 16 => reg 1 ]
> [ cmp eq reg 1 0x0701000a ]
> [ immediate reg 1 0x6ea09c2e 0x00009625 ]
> [ payload write reg 1 => 6b @ link header + 0 csum_type 0 csum_off 0 csum_flags 0x0 ]
> [ immediate reg 1 0xfffffffa 0x0000ffff ]
> [ payload write reg 1 => 6b @ link header + 6 csum_type 0 csum_off 0 csum_flags 0x0 ]
> [ objref type 6 name encap ]
> [ immediate reg 1 0x00000019 ]
> [ fwd sreg_dev 1 ]
>
>
> # nft add chain netdev firewall aclin { type filter hook ingress device gretap priority - 300 \; }
> # nft --debug=netlink add rule netdev firewall aclin ip daddr 10.0.0.7 tunnel tunid 1000 tunnel tundst 172.168.152.75 tunnel tunsrc 172.168.152.241 tunnel name decap @ll,0,48 set 0x0000525400001275 @ll,48,48 set 0xfaffffffffff fwd to mlx_pf0vf0
> [ meta load protocol => reg 1 ]
> [ cmp eq reg 1 0x00000008 ]
> [ payload load 4b @ network header + 16 => reg 1 ]
> [ cmp eq reg 1 0x0700000a ]
> [ tunnel load id => reg 1 ]
> [ cmp eq reg 1 0x000003e8 ]
> [ tunnel load tun_dst => reg 1 ]
> [ cmp eq reg 1 0xaca8984b ]
> [ tunnel load tun_src => reg 1 ]
> [ cmp eq reg 1 0xaca898f1 ]
> [ objref type 6 name decap ]
> [ immediate reg 1 0x00005452 0x00007512 ]
> [ payload write reg 1 => 6b @ link header + 0 csum_type 0 csum_off 0 csum_flags 0x0 ]
> [ immediate reg 1 0xfffffffa 0x0000ffff ]
> [ payload write reg 1 => 6b @ link header + 6 csum_type 0 csum_off 0 csum_flags 0x0 ]
> [ immediate reg 1 0x0000000f ]
> [ fwd sreg_dev 1 ]
>
> wenxu (9):
> netfilter: nf_flow_offload: add net in offload_ctx
> netfilter: nf_tables_offload: add offload_actions callback
> netfilter: nft_fwd_netdev: add fw_netdev action support
> netfilter: nft_payload: add nft_set_payload offload support
> netfilter: nft_tunnel: support NFT_TUNNEL_SRC/DST_IP 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 | 10 ++-
> include/net/netfilter/nf_tables_offload.h | 7 +-
> include/uapi/linux/netfilter/nf_tables.h | 3 +
> net/netfilter/nf_tables_api.c | 2 +-
> net/netfilter/nf_tables_offload.c | 7 +-
> net/netfilter/nft_fwd_netdev.c | 27 +++++++
> net/netfilter/nft_immediate.c | 2 +-
> net/netfilter/nft_objref.c | 15 ++++
> net/netfilter/nft_payload.c | 56 ++++++++++++++
> net/netfilter/nft_tunnel.c | 123 ++++++++++++++++++++++++++----
> 10 files changed, 230 insertions(+), 22 deletions(-)
>
On Thu, Aug 01, 2019 at 10:01:22PM +0800, wenxu@ucloud.cn wrote: > From: wenxu <wenxu@ucloud.cn> > > Add new two NFT_TUNNEL_SRC/DST_IP match in nft_tunnel > > Signed-off-by: wenxu <wenxu@ucloud.cn> > --- > v3: no change > > include/uapi/linux/netfilter/nf_tables.h | 2 ++ > net/netfilter/nft_tunnel.c | 46 +++++++++++++++++++++++++------- > 2 files changed, 38 insertions(+), 10 deletions(-) > > diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h > index 82abaa1..173690a 100644 > --- a/include/uapi/linux/netfilter/nf_tables.h > +++ b/include/uapi/linux/netfilter/nf_tables.h > @@ -1765,6 +1765,8 @@ enum nft_tunnel_key_attributes { > enum nft_tunnel_keys { > NFT_TUNNEL_PATH, > NFT_TUNNEL_ID, > + NFT_TUNNEL_SRC_IP, > + NFT_TUNNEL_DST_IP, > __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 3d4c2ae..e218163 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; > +} Make an initial patch to add nft_tunnel_mode_validate(). > 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); [...] > + case NFT_TUNNEL_DST_IP: > + if (!tun_info) { > + regs->verdict.code = NFT_BREAK; > + return; > + } > + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) > + *dest = ntohl(tun_info->key.u.ipv4.dst); No need to convert this from network to host endianess. > + else > + regs->verdict.code = NFT_BREAK; > + break; > default: > WARN_ON(1); > regs->verdict.code = NFT_BREAK; > @@ -86,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_SRC_IP: > + case NFT_TUNNEL_DST_IP: Missing policy updates, ie. nft_tunnel_key_policy. I would take an initial patchset with two patches to add support for this to the tunnel extension. IPv6 is missing though, you could add it too to this patchset so this becomes a patchset compose of three patches, I'd suggest.
On 8/14/2019 2:19 AM, Pablo Neira Ayuso wrote: > On Thu, Aug 01, 2019 at 10:01:22PM +0800, wenxu@ucloud.cn wrote: >> From: wenxu <wenxu@ucloud.cn> >> >> Add new two NFT_TUNNEL_SRC/DST_IP match in nft_tunnel >> >> Signed-off-by: wenxu <wenxu@ucloud.cn> >> --- >> v3: no change >> >> include/uapi/linux/netfilter/nf_tables.h | 2 ++ >> net/netfilter/nft_tunnel.c | 46 +++++++++++++++++++++++++------- >> 2 files changed, 38 insertions(+), 10 deletions(-) >> >> diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h >> index 82abaa1..173690a 100644 >> --- a/include/uapi/linux/netfilter/nf_tables.h >> +++ b/include/uapi/linux/netfilter/nf_tables.h >> @@ -1765,6 +1765,8 @@ enum nft_tunnel_key_attributes { >> enum nft_tunnel_keys { >> NFT_TUNNEL_PATH, >> NFT_TUNNEL_ID, >> + NFT_TUNNEL_SRC_IP, >> + NFT_TUNNEL_DST_IP, >> __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 3d4c2ae..e218163 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; >> +} > Make an initial patch to add nft_tunnel_mode_validate(). > >> 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); > [...] >> + case NFT_TUNNEL_DST_IP: >> + if (!tun_info) { >> + regs->verdict.code = NFT_BREAK; >> + return; >> + } >> + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) >> + *dest = ntohl(tun_info->key.u.ipv4.dst); > No need to convert this from network to host endianess. > >> + else >> + regs->verdict.code = NFT_BREAK; >> + break; >> default: >> WARN_ON(1); >> regs->verdict.code = NFT_BREAK; >> @@ -86,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_SRC_IP: >> + case NFT_TUNNEL_DST_IP: > Missing policy updates, ie. nft_tunnel_key_policy. I don't understand why it need update nft_tunnel_key_policy which is used for tunnel_obj action. This NFT_TUNNEL_SRC/DST_IP is used for tunnel_expr >
On Wed, Aug 14, 2019 at 03:54:03PM +0800, wenxu wrote:
>
> On 8/14/2019 2:19 AM, Pablo Neira Ayuso wrote:
> > On Thu, Aug 01, 2019 at 10:01:22PM +0800, wenxu@ucloud.cn wrote:
> >> From: wenxu <wenxu@ucloud.cn>
> >>
> >> Add new two NFT_TUNNEL_SRC/DST_IP match in nft_tunnel
> >>
> >> Signed-off-by: wenxu <wenxu@ucloud.cn>
> >> ---
> >> v3: no change
> >>
> >> include/uapi/linux/netfilter/nf_tables.h | 2 ++
> >> net/netfilter/nft_tunnel.c | 46 +++++++++++++++++++++++++-------
> >> 2 files changed, 38 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
> >> index 82abaa1..173690a 100644
> >> --- a/include/uapi/linux/netfilter/nf_tables.h
> >> +++ b/include/uapi/linux/netfilter/nf_tables.h
> >> @@ -1765,6 +1765,8 @@ enum nft_tunnel_key_attributes {
> >> enum nft_tunnel_keys {
> >> NFT_TUNNEL_PATH,
> >> NFT_TUNNEL_ID,
> >> + NFT_TUNNEL_SRC_IP,
> >> + NFT_TUNNEL_DST_IP,
> >> __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 3d4c2ae..e218163 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;
> >> +}
> > Make an initial patch to add nft_tunnel_mode_validate().
> >
> >> 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);
> > [...]
> >> + case NFT_TUNNEL_DST_IP:
> >> + if (!tun_info) {
> >> + regs->verdict.code = NFT_BREAK;
> >> + return;
> >> + }
> >> + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode))
> >> + *dest = ntohl(tun_info->key.u.ipv4.dst);
> > No need to convert this from network to host endianess.
> >
> >> + else
> >> + regs->verdict.code = NFT_BREAK;
> >> + break;
> >> default:
> >> WARN_ON(1);
> >> regs->verdict.code = NFT_BREAK;
> >> @@ -86,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_SRC_IP:
> >> + case NFT_TUNNEL_DST_IP:
> > Missing policy updates, ie. nft_tunnel_key_policy.
>
> I don't understand why it need update nft_tunnel_key_policy
> which is used for tunnel_obj action. This NFT_TUNNEL_SRC/DST_IP is used
> for tunnel_expr
It seems there is no policy object for _get_eval(), add it.
Thanks.
On Wed, Aug 14, 2019 at 10:00:37AM +0200, Pablo Neira Ayuso wrote:
[...]
> > >> @@ -86,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_SRC_IP:
> > >> + case NFT_TUNNEL_DST_IP:
> > > Missing policy updates, ie. nft_tunnel_key_policy.
> >
> > I don't understand why it need update nft_tunnel_key_policy
> > which is used for tunnel_obj action. This NFT_TUNNEL_SRC/DST_IP is used
> > for tunnel_expr
>
> It seems there is no policy object for _get_eval(), add it.
There is. It is actually nft_tunnel_policy.
On 8/14/2019 4:00 PM, Pablo Neira Ayuso wrote: > On Wed, Aug 14, 2019 at 03:54:03PM +0800, wenxu wrote: >> On 8/14/2019 2:19 AM, Pablo Neira Ayuso wrote: >>> On Thu, Aug 01, 2019 at 10:01:22PM +0800, wenxu@ucloud.cn wrote: >>>> From: wenxu <wenxu@ucloud.cn> >>>> >>>> Add new two NFT_TUNNEL_SRC/DST_IP match in nft_tunnel >>>> >>>> Signed-off-by: wenxu <wenxu@ucloud.cn> >>>> --- >>>> v3: no change >>>> >>>> include/uapi/linux/netfilter/nf_tables.h | 2 ++ >>>> net/netfilter/nft_tunnel.c | 46 +++++++++++++++++++++++++------- >>>> 2 files changed, 38 insertions(+), 10 deletions(-) >>>> >>>> diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h >>>> index 82abaa1..173690a 100644 >>>> --- a/include/uapi/linux/netfilter/nf_tables.h >>>> +++ b/include/uapi/linux/netfilter/nf_tables.h >>>> @@ -1765,6 +1765,8 @@ enum nft_tunnel_key_attributes { >>>> enum nft_tunnel_keys { >>>> NFT_TUNNEL_PATH, >>>> NFT_TUNNEL_ID, >>>> + NFT_TUNNEL_SRC_IP, >>>> + NFT_TUNNEL_DST_IP, >>>> __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 3d4c2ae..e218163 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; >>>> +} >>> Make an initial patch to add nft_tunnel_mode_validate(). >>> >>>> 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); >>> [...] >>>> + case NFT_TUNNEL_DST_IP: >>>> + if (!tun_info) { >>>> + regs->verdict.code = NFT_BREAK; >>>> + return; >>>> + } >>>> + if (nft_tunnel_mode_validate(priv->mode, tun_info->mode)) >>>> + *dest = ntohl(tun_info->key.u.ipv4.dst); >>> No need to convert this from network to host endianess. >>> >>>> + else >>>> + regs->verdict.code = NFT_BREAK; >>>> + break; >>>> default: >>>> WARN_ON(1); >>>> regs->verdict.code = NFT_BREAK; >>>> @@ -86,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_SRC_IP: >>>> + case NFT_TUNNEL_DST_IP: >>> Missing policy updates, ie. nft_tunnel_key_policy. >> I don't understand why it need update nft_tunnel_key_policy >> which is used for tunnel_obj action. This NFT_TUNNEL_SRC/DST_IP is used >> for tunnel_expr > It seems there is no policy object for _get_eval(), add it. you means like the NFTA_TUNNEL_KEY_IP have policy NFTA_TUNNEL_KEY_IP_DST and NFTA_TUNNEL_KEY_IP_SRC But I think it doesn't need to nested the policy for NFT_TUNNEL_IP which contains NFT_TUNNEL_IP_SRC and NFT_TUNNE_IP_DST. A match rule only can match one field (NFT_TUNNEL_ID, NFT_TUNNEL_IP_SRC, NFT_TUNNEL_IP_DST, ieg) > > Thanks. >
On 8/14/2019 4:19 PM, Pablo Neira Ayuso wrote:
> On Wed, Aug 14, 2019 at 10:00:37AM +0200, Pablo Neira Ayuso wrote:
> [...]
>>>>> @@ -86,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_SRC_IP:
>>>>> + case NFT_TUNNEL_DST_IP:
>>>> Missing policy updates, ie. nft_tunnel_key_policy.
>>> I don't understand why it need update nft_tunnel_key_policy
>>> which is used for tunnel_obj action. This NFT_TUNNEL_SRC/DST_IP is used
>>> for tunnel_expr
>> It seems there is no policy object for _get_eval(), add it.
> There is. It is actually nft_tunnel_policy.
nft_tunnel_policy contain a NFTA_TUNNEL_KEY
NFTA_TUNNEL_KEY support NFT_TUNNEL_ID, NFT_TUNNEL_SRC/DST_IP
I think the NFTA_TUNNEL_KEY means a match key which can be tun_id, tun_src, tun_dst
On Wed, Aug 14, 2019 at 04:28:43PM +0800, wenxu wrote:
>
> On 8/14/2019 4:19 PM, Pablo Neira Ayuso wrote:
> > On Wed, Aug 14, 2019 at 10:00:37AM +0200, Pablo Neira Ayuso wrote:
> > [...]
> >>>>> @@ -86,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_SRC_IP:
> >>>>> + case NFT_TUNNEL_DST_IP:
> >>>> Missing policy updates, ie. nft_tunnel_key_policy.
> >>> I don't understand why it need update nft_tunnel_key_policy
> >>> which is used for tunnel_obj action. This NFT_TUNNEL_SRC/DST_IP is used
> >>> for tunnel_expr
> >> It seems there is no policy object for _get_eval(), add it.
> > There is. It is actually nft_tunnel_policy.
>
> nft_tunnel_policy contain a NFTA_TUNNEL_KEY
>
> NFTA_TUNNEL_KEY support NFT_TUNNEL_ID, NFT_TUNNEL_SRC/DST_IP
>
> I think the NFTA_TUNNEL_KEY means a match key which can be tun_id, tun_src, tun_dst
Correct.