Commit b9242da6 authored by David S. Miller's avatar David S. Miller

Merge branch 'nf_tables_offload-vlan-matching-support'

Pablo Neira Ayuso says:

====================
nf_tables_offload: vlan matching support

The following patchset contains Netfilter support for vlan matching
offloads:

1) Constify nft_reg_load() as a preparation patch.
2) Restrict rule matching to ingress interface type ARPHRD_ETHER.
3) Add new vlan_tci field to flow_dissector_key_vlan structure,
   to allow to set up vlan_id, vlan_dei and vlan_priority in one go.
4) C-VLAN matching support.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2f1d370b 89d8fd44
...@@ -48,9 +48,12 @@ struct flow_dissector_key_tags { ...@@ -48,9 +48,12 @@ struct flow_dissector_key_tags {
}; };
struct flow_dissector_key_vlan { struct flow_dissector_key_vlan {
u16 vlan_id:12, union {
vlan_dei:1, u16 vlan_id:12,
vlan_priority:3; vlan_dei:1,
vlan_priority:3;
__be16 vlan_tci;
};
__be16 vlan_tpid; __be16 vlan_tpid;
}; };
...@@ -203,9 +206,11 @@ struct flow_dissector_key_ip { ...@@ -203,9 +206,11 @@ struct flow_dissector_key_ip {
/** /**
* struct flow_dissector_key_meta: * struct flow_dissector_key_meta:
* @ingress_ifindex: ingress ifindex * @ingress_ifindex: ingress ifindex
* @ingress_iftype: ingress interface type
*/ */
struct flow_dissector_key_meta { struct flow_dissector_key_meta {
int ingress_ifindex; int ingress_ifindex;
u16 ingress_iftype;
}; };
/** /**
......
...@@ -114,7 +114,7 @@ static inline void nft_reg_store8(u32 *dreg, u8 val) ...@@ -114,7 +114,7 @@ static inline void nft_reg_store8(u32 *dreg, u8 val)
*(u8 *)dreg = val; *(u8 *)dreg = val;
} }
static inline u8 nft_reg_load8(u32 *sreg) static inline u8 nft_reg_load8(const u32 *sreg)
{ {
return *(u8 *)sreg; return *(u8 *)sreg;
} }
...@@ -125,7 +125,7 @@ static inline void nft_reg_store16(u32 *dreg, u16 val) ...@@ -125,7 +125,7 @@ static inline void nft_reg_store16(u32 *dreg, u16 val)
*(u16 *)dreg = val; *(u16 *)dreg = val;
} }
static inline u16 nft_reg_load16(u32 *sreg) static inline u16 nft_reg_load16(const u32 *sreg)
{ {
return *(u16 *)sreg; return *(u16 *)sreg;
} }
...@@ -135,7 +135,7 @@ static inline void nft_reg_store64(u32 *dreg, u64 val) ...@@ -135,7 +135,7 @@ static inline void nft_reg_store64(u32 *dreg, u64 val)
put_unaligned(val, (u64 *)dreg); put_unaligned(val, (u64 *)dreg);
} }
static inline u64 nft_reg_load64(u32 *sreg) static inline u64 nft_reg_load64(const u32 *sreg)
{ {
return get_unaligned((u64 *)sreg); return get_unaligned((u64 *)sreg);
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/if_arp.h>
#include <linux/netfilter/nf_tables.h> #include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h> #include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables_offload.h> #include <net/netfilter/nf_tables_offload.h>
...@@ -125,6 +126,11 @@ static int __nft_cmp_offload(struct nft_offload_ctx *ctx, ...@@ -125,6 +126,11 @@ static int __nft_cmp_offload(struct nft_offload_ctx *ctx,
flow->match.dissector.used_keys |= BIT(reg->key); flow->match.dissector.used_keys |= BIT(reg->key);
flow->match.dissector.offset[reg->key] = reg->base_offset; flow->match.dissector.offset[reg->key] = reg->base_offset;
if (reg->key == FLOW_DISSECTOR_KEY_META &&
reg->offset == offsetof(struct nft_flow_key, meta.ingress_iftype) &&
nft_reg_load16(priv->data.data) != ARPHRD_ETHER)
return -EOPNOTSUPP;
nft_offload_update_dependency(ctx, &priv->data, priv->len); nft_offload_update_dependency(ctx, &priv->data, priv->len);
return 0; return 0;
......
...@@ -551,6 +551,10 @@ static int nft_meta_get_offload(struct nft_offload_ctx *ctx, ...@@ -551,6 +551,10 @@ static int nft_meta_get_offload(struct nft_offload_ctx *ctx,
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_META, meta, NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_META, meta,
ingress_ifindex, sizeof(__u32), reg); ingress_ifindex, sizeof(__u32), reg);
break; break;
case NFT_META_IIFTYPE:
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_META, meta,
ingress_iftype, sizeof(__u16), reg);
break;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -182,6 +182,44 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx, ...@@ -182,6 +182,44 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
dst, ETH_ALEN, reg); dst, ETH_ALEN, reg);
break; break;
case offsetof(struct ethhdr, h_proto):
if (priv->len != sizeof(__be16))
return -EOPNOTSUPP;
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic,
n_proto, sizeof(__be16), reg);
nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
break;
case offsetof(struct vlan_ethhdr, h_vlan_TCI):
if (priv->len != sizeof(__be16))
return -EOPNOTSUPP;
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_VLAN, vlan,
vlan_tci, sizeof(__be16), reg);
break;
case offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto):
if (priv->len != sizeof(__be16))
return -EOPNOTSUPP;
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_VLAN, vlan,
vlan_tpid, sizeof(__be16), reg);
nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
break;
case offsetof(struct vlan_ethhdr, h_vlan_TCI) + sizeof(struct vlan_hdr):
if (priv->len != sizeof(__be16))
return -EOPNOTSUPP;
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_CVLAN, vlan,
vlan_tci, sizeof(__be16), reg);
break;
case offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto) +
sizeof(struct vlan_hdr):
if (priv->len != sizeof(__be16))
return -EOPNOTSUPP;
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_CVLAN, vlan,
vlan_tpid, sizeof(__be16), reg);
break;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment