]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
netfilter: nftables_offload: set address type in control dissector
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 25 Nov 2020 22:50:07 +0000 (23:50 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 27 Nov 2020 11:10:46 +0000 (12:10 +0100)
This patch adds nft_flow_rule_set_addr_type() to set the address type
from the nft_payload expression accordingly.

If the address type is not set in the control dissector then a rule that
matches either on source or destination IP address does not work.

After this patch, nft hardware offload generates the flow dissector
configuration as tc-flower does to match on an IP address.

This patch has been also tested functionally to make sure packets are
filtered out by the NIC.

This is also getting the code aligned with the existing netfilter flow
offload infrastructure which is also setting the control dissector.

Fixes: c9626a2cbdb2 ("netfilter: nf_tables: add hardware offload support")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_tables_offload.h
net/netfilter/nf_tables_offload.c
net/netfilter/nft_payload.c

index ea7d1d78b92d2a6a64f6017d7ffa1fe0af142997..bddd34c5bd79c7ecde163b19ed0753caff186bc4 100644 (file)
@@ -37,6 +37,7 @@ void nft_offload_update_dependency(struct nft_offload_ctx *ctx,
 
 struct nft_flow_key {
        struct flow_dissector_key_basic                 basic;
+       struct flow_dissector_key_control               control;
        union {
                struct flow_dissector_key_ipv4_addrs    ipv4;
                struct flow_dissector_key_ipv6_addrs    ipv6;
@@ -62,6 +63,9 @@ struct nft_flow_rule {
 
 #define NFT_OFFLOAD_F_ACTION   (1 << 0)
 
+void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow,
+                                enum flow_dissector_key_id addr_type);
+
 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);
index 9f625724a20fc27ea54ca1cdd3e747d170260410..9ae14270c543e045c16e75648dfb24b8a8a65633 100644 (file)
@@ -28,6 +28,23 @@ static struct nft_flow_rule *nft_flow_rule_alloc(int num_actions)
        return flow;
 }
 
+void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow,
+                                enum flow_dissector_key_id addr_type)
+{
+       struct nft_flow_match *match = &flow->match;
+       struct nft_flow_key *mask = &match->mask;
+       struct nft_flow_key *key = &match->key;
+
+       if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL))
+               return;
+
+       key->control.addr_type = addr_type;
+       mask->control.addr_type = 0xffff;
+       match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL);
+       match->dissector.offset[FLOW_DISSECTOR_KEY_CONTROL] =
+               offsetof(struct nft_flow_key, control);
+}
+
 struct nft_flow_rule *nft_flow_rule_create(struct net *net,
                                           const struct nft_rule *rule)
 {
index dcd3c7b8a367c77d8a1f141e81489347de640aa9..bbf811d030d5414420b348d8b3f98ed571af94d4 100644 (file)
@@ -244,6 +244,7 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
                                  sizeof(struct in_addr), reg);
+               nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV4_ADDRS);
                break;
        case offsetof(struct iphdr, daddr):
                if (priv->len != sizeof(struct in_addr))
@@ -251,6 +252,7 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
                                  sizeof(struct in_addr), reg);
+               nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV4_ADDRS);
                break;
        case offsetof(struct iphdr, protocol):
                if (priv->len != sizeof(__u8))
@@ -280,6 +282,7 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
                                  sizeof(struct in6_addr), reg);
+               nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV6_ADDRS);
                break;
        case offsetof(struct ipv6hdr, daddr):
                if (priv->len != sizeof(struct in6_addr))
@@ -287,6 +290,7 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
 
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
                                  sizeof(struct in6_addr), reg);
+               nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV6_ADDRS);
                break;
        case offsetof(struct ipv6hdr, nexthdr):
                if (priv->len != sizeof(__u8))