Commit f531d13b authored by Eyal Birger's avatar Eyal Birger Committed by Steffen Klassert
Browse files

xfrm: support sending NAT keepalives in ESP in UDP states



Add the ability to send out RFC-3948 NAT keepalives from the xfrm stack.

To use, Userspace sets an XFRM_NAT_KEEPALIVE_INTERVAL integer property when
creating XFRM outbound states which denotes the number of seconds between
keepalive messages.

Keepalive messages are sent from a per net delayed work which iterates over
the xfrm states. The logic is guarded by the xfrm state spinlock due to the
xfrm state walk iterator.

Possible future enhancements:

- Adding counters to keep track of sent keepalives.
- deduplicate NAT keepalives between states sharing the same nat keepalive
  parameters.
- provisioning hardware offloads for devices capable of implementing this.
- revise xfrm state list to use an rcu list in order to avoid running this
  under spinlock.

Suggested-by: default avatarPaul Wouters <paul.wouters@aiven.io>
Tested-by: default avatarPaul Wouters <paul.wouters@aiven.io>
Tested-by: default avatarAntony Antony <antony.antony@secunet.com>
Signed-off-by: default avatarEyal Birger <eyal.birger@gmail.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 5233a55a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <net/flow.h>
#include <net/neighbour.h>
#include <net/sock.h>
#include <net/ipv6.h>

/* structs from net/ip6_fib.h */
struct fib6_info;
@@ -72,6 +73,8 @@ struct ipv6_stub {
			     int (*output)(struct net *, struct sock *, struct sk_buff *));
	struct net_device *(*ipv6_dev_find)(struct net *net, const struct in6_addr *addr,
					    struct net_device *dev);
	int (*ip6_xmit)(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
			__u32 mark, struct ipv6_txoptions *opt, int tclass, u32 priority);
};
extern const struct ipv6_stub *ipv6_stub __read_mostly;

+1 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ struct netns_xfrm {

	spinlock_t xfrm_policy_lock;
	struct mutex xfrm_cfg_mutex;
	struct delayed_work	nat_keepalive_work;
};

#endif
+10 −0
Original line number Diff line number Diff line
@@ -229,6 +229,10 @@ struct xfrm_state {
	struct xfrm_encap_tmpl	*encap;
	struct sock __rcu	*encap_sk;

	/* NAT keepalive */
	u32			nat_keepalive_interval; /* seconds */
	time64_t		nat_keepalive_expiration;

	/* Data for care-of address */
	xfrm_address_t	*coaddr;

@@ -2203,4 +2207,10 @@ static inline int register_xfrm_state_bpf(void)
}
#endif

int xfrm_nat_keepalive_init(unsigned short family);
void xfrm_nat_keepalive_fini(unsigned short family);
int xfrm_nat_keepalive_net_init(struct net *net);
int xfrm_nat_keepalive_net_fini(struct net *net);
void xfrm_nat_keepalive_state_updated(struct xfrm_state *x);

#endif	/* _NET_XFRM_H */
+1 −0
Original line number Diff line number Diff line
@@ -321,6 +321,7 @@ enum xfrm_attr_type_t {
	XFRMA_IF_ID,		/* __u32 */
	XFRMA_MTIMER_THRESH,	/* __u32 in seconds for input SA */
	XFRMA_SA_DIR,		/* __u8 */
	XFRMA_NAT_KEEPALIVE_INTERVAL,	/* __u32 in seconds for NAT keepalive */
	__XFRMA_MAX

#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK	/* Compatibility */
+1 −0
Original line number Diff line number Diff line
@@ -1060,6 +1060,7 @@ static const struct ipv6_stub ipv6_stub_impl = {
	.nd_tbl	= &nd_tbl,
	.ipv6_fragment = ip6_fragment,
	.ipv6_dev_find = ipv6_dev_find,
	.ip6_xmit = ip6_xmit,
};

static const struct ipv6_bpf_stub ipv6_bpf_stub_impl = {
Loading