Commit 12dee519 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

1) Move struct nft_payload_set definition to .c file where it is
   only used.

2) Shrink transport and inner header offset fields in the nft_pktinfo
   structure to 16-bits, from Florian Westphal.

3) Get rid of nft_objref Kbuild toggle, make it built-in into
   nf_tables. This expression is used to instantiate conntrack helpers
   in nftables. After removing the conntrack helper auto-assignment
   toggle it this feature became more important so move it to the nf_tables
   core module. Also from Florian.

4) Extend the existing function to calculate payload inner header offset
   to deal with the GRE and IPIP transport protocols.

6) Add inner expression support for nf_tables. This new expression
   provides a packet parser for tunneled packets which uses a userspace
   description of the expected inner headers. The inner expression
   invokes the payload expression (via direct call) to match on the
   inner header protocol fields using the inner link, network and
   transport header offsets.

   An example of the bytecode generated from userspace to match on
   IP source encapsulated in a VxLAN packet:

   # nft --debug=netlink add rule netdev x y udp dport 4789 vxlan ip saddr 1.2.3.4
     netdev x y
       [ meta load l4proto => reg 1 ]
       [ cmp eq reg 1 0x00000011 ]
       [ payload load 2b @ transport header + 2 => reg 1 ]
       [ cmp eq reg 1 0x0000b512 ]
       [ inner type vxlan hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
       [ cmp eq reg 1 0x00000008 ]
       [ inner type vxlan hdrsize 8 flags f [ payload load 4b @ network header + 12 => reg 1 ] ]
       [ cmp eq reg 1 0x04030201 ]

7) Store inner link, network and transport header offsets in percpu
   area to parse inner packet header once only. Matching on a different
   tunnel type invalidates existing offsets in the percpu area and it
   invokes the inner tunnel parser again.

8) Add support for inner meta matching. This support for
   NFTA_META_PROTOCOL, which specifies the inner ethertype, and
   NFT_META_L4PROTO, which specifies the inner transport protocol.

9) Extend nft_inner to parse GENEVE optional fields to calculate the
   link layer offset.

10) Update inner expression so tunnel offset points to GRE header
    to normalize tunnel header handling. This also allows to perform
    different interpretations of the GRE header from userspace.

* git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
  netfilter: nft_inner: set tunnel offset to GRE header offset
  netfilter: nft_inner: add geneve support
  netfilter: nft_meta: add inner match support
  netfilter: nft_inner: add percpu inner context
  netfilter: nft_inner: support for inner tunnel header matching
  netfilter: nft_payload: access ipip payload for inner offset
  netfilter: nft_payload: access GRE payload via inner offset
  netfilter: nft_objref: make it builtin
  netfilter: nf_tables: reduce nft_pktinfo by 8 bytes
  netfilter: nft_payload: move struct nft_payload_set definition where it belongs
====================

Link: https://lore.kernel.org/r/20221026132227.3287-1-pablo@netfilter.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 148b811c 91619eb6
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ struct module;
enum {
	NFT_PKTINFO_L4PROTO	= (1 << 0),
	NFT_PKTINFO_INNER	= (1 << 1),
	NFT_PKTINFO_INNER_FULL	= (1 << 2),
};

struct nft_pktinfo {
@@ -32,8 +33,8 @@ struct nft_pktinfo {
	u8				flags;
	u8				tprot;
	u16				fragoff;
	unsigned int			thoff;
	unsigned int			inneroff;
	u16				thoff;
	u16				inneroff;
};

static inline struct sock *nft_sk(const struct nft_pktinfo *pkt)
@@ -375,6 +376,10 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
	return (void *)expr->data;
}

struct nft_expr_info;

int nft_expr_inner_parse(const struct nft_ctx *ctx, const struct nlattr *nla,
			 struct nft_expr_info *info);
int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src);
void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr);
int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
@@ -864,6 +869,7 @@ struct nft_expr_type {
						       const struct nlattr * const tb[]);
	void				(*release_ops)(const struct nft_expr_ops *ops);
	const struct nft_expr_ops	*ops;
	const struct nft_expr_ops	*inner_ops;
	struct list_head		list;
	const char			*name;
	struct module			*owner;
+26 −10
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ extern struct nft_expr_type nft_meta_type;
extern struct nft_expr_type nft_rt_type;
extern struct nft_expr_type nft_exthdr_type;
extern struct nft_expr_type nft_last_type;
extern struct nft_expr_type nft_objref_type;
extern struct nft_expr_type nft_inner_type;

#ifdef CONFIG_NETWORK_SECMARK
extern struct nft_object_type nft_secmark_obj_type;
@@ -66,16 +68,6 @@ struct nft_payload {
	u8			dreg;
};

struct nft_payload_set {
	enum nft_payload_bases	base:8;
	u8			offset;
	u8			len;
	u8			sreg;
	u8			csum_type;
	u8			csum_offset;
	u8			csum_flags;
};

extern const struct nft_expr_ops nft_payload_fast_ops;

extern const struct nft_expr_ops nft_bitwise_fast_ops;
@@ -148,4 +140,28 @@ void nft_rt_get_eval(const struct nft_expr *expr,
		     struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_counter_eval(const struct nft_expr *expr, struct nft_regs *regs,
                      const struct nft_pktinfo *pkt);

enum {
	NFT_PAYLOAD_CTX_INNER_TUN	= (1 << 0),
	NFT_PAYLOAD_CTX_INNER_LL	= (1 << 1),
	NFT_PAYLOAD_CTX_INNER_NH	= (1 << 2),
	NFT_PAYLOAD_CTX_INNER_TH	= (1 << 3),
};

struct nft_inner_tun_ctx {
	u16	type;
	u16	inner_tunoff;
	u16	inner_lloff;
	u16	inner_nhoff;
	u16	inner_thoff;
	__be16	llproto;
	u8	l4proto;
	u8      flags;
};

int nft_payload_inner_offset(const struct nft_pktinfo *pkt);
void nft_payload_inner_eval(const struct nft_expr *expr, struct nft_regs *regs,
			    const struct nft_pktinfo *pkt,
			    struct nft_inner_tun_ctx *ctx);

#endif /* _NET_NF_TABLES_CORE_H */
+4 −0
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
		return -1;
	else if (len < thoff)
		return -1;
	else if (thoff < sizeof(*iph))
		return -1;

	pkt->flags = NFT_PKTINFO_L4PROTO;
	pkt->tprot = iph->protocol;
@@ -69,6 +71,8 @@ static inline int nft_set_pktinfo_ipv4_ingress(struct nft_pktinfo *pkt)
		return -1;
	} else if (len < thoff) {
		goto inhdr_error;
	} else if (thoff < sizeof(*iph)) {
		return -1;
	}

	pkt->flags = NFT_PKTINFO_L4PROTO;
+3 −3
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt)
	unsigned short frag_off;

	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
	if (protohdr < 0) {
	if (protohdr < 0 || thoff > U16_MAX) {
		nft_set_pktinfo_unspec(pkt);
		return;
	}
@@ -47,7 +47,7 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
		return -1;

	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
	if (protohdr < 0)
	if (protohdr < 0 || thoff > U16_MAX)
		return -1;

	pkt->flags = NFT_PKTINFO_L4PROTO;
@@ -93,7 +93,7 @@ static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt)
	}

	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
	if (protohdr < 0)
	if (protohdr < 0 || thoff > U16_MAX)
		goto inhdr_error;

	pkt->flags = NFT_PKTINFO_L4PROTO;
+6 −0
Original line number Diff line number Diff line
@@ -46,4 +46,10 @@ int nft_meta_set_validate(const struct nft_ctx *ctx,

bool nft_meta_get_reduce(struct nft_regs_track *track,
			 const struct nft_expr *expr);

struct nft_inner_tun_ctx;
void nft_meta_inner_eval(const struct nft_expr *expr,
			 struct nft_regs *regs, const struct nft_pktinfo *pkt,
			 struct nft_inner_tun_ctx *tun_ctx);

#endif
Loading