Skip to content

Commit 7028b7a

Browse files
ebirgerNipaLocal
authored and
NipaLocal
committed
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: Paul Wouters <[email protected]> Signed-off-by: Eyal Birger <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent 0e1c441 commit 7028b7a

File tree

12 files changed

+356
-4
lines changed

12 files changed

+356
-4
lines changed

include/net/ipv6_stubs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <net/flow.h>
1010
#include <net/neighbour.h>
1111
#include <net/sock.h>
12+
#include <net/ipv6.h>
1213

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

include/net/netns/xfrm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ struct netns_xfrm {
8383

8484
spinlock_t xfrm_policy_lock;
8585
struct mutex xfrm_cfg_mutex;
86+
struct delayed_work nat_keepalive_work;
8687
};
8788

8889
#endif

include/net/xfrm.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ struct xfrm_state {
227227
struct xfrm_encap_tmpl *encap;
228228
struct sock __rcu *encap_sk;
229229

230+
/* NAT keepalive */
231+
u32 nat_keepalive_interval; /* seconds */
232+
time64_t nat_keepalive_expiration;
233+
230234
/* Data for care-of address */
231235
xfrm_address_t *coaddr;
232236

@@ -2190,4 +2194,10 @@ static inline int register_xfrm_interface_bpf(void)
21902194

21912195
#endif
21922196

2197+
int xfrm_nat_keepalive_init(unsigned short family);
2198+
void xfrm_nat_keepalive_fini(unsigned short family);
2199+
int xfrm_nat_keepalive_net_init(struct net *net);
2200+
int xfrm_nat_keepalive_net_fini(struct net *net);
2201+
void xfrm_nat_keepalive_state_updated(struct xfrm_state *x);
2202+
21932203
#endif /* _NET_XFRM_H */

include/uapi/linux/xfrm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ enum xfrm_attr_type_t {
315315
XFRMA_SET_MARK_MASK, /* __u32 */
316316
XFRMA_IF_ID, /* __u32 */
317317
XFRMA_MTIMER_THRESH, /* __u32 in seconds for input SA */
318+
XFRMA_NAT_KEEPALIVE_INTERVAL, /* __u32 in seconds for NAT keepalive */
318319
__XFRMA_MAX
319320

320321
#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */

net/ipv6/af_inet6.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,7 @@ static const struct ipv6_stub ipv6_stub_impl = {
10561056
.nd_tbl = &nd_tbl,
10571057
.ipv6_fragment = ip6_fragment,
10581058
.ipv6_dev_find = ipv6_dev_find,
1059+
.ip6_xmit = ip6_xmit,
10591060
};
10601061

10611062
static const struct ipv6_bpf_stub ipv6_bpf_stub_impl = {

net/ipv6/xfrm6_policy.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,14 @@ int __init xfrm6_init(void)
285285
ret = register_pernet_subsys(&xfrm6_net_ops);
286286
if (ret)
287287
goto out_protocol;
288+
289+
ret = xfrm_nat_keepalive_init(AF_INET6);
290+
if (ret)
291+
goto out_nat_keepalive;
288292
out:
289293
return ret;
294+
out_nat_keepalive:
295+
unregister_pernet_subsys(&xfrm6_net_ops);
290296
out_protocol:
291297
xfrm6_protocol_fini();
292298
out_state:
@@ -298,6 +304,7 @@ int __init xfrm6_init(void)
298304

299305
void xfrm6_fini(void)
300306
{
307+
xfrm_nat_keepalive_fini(AF_INET6);
301308
unregister_pernet_subsys(&xfrm6_net_ops);
302309
xfrm6_protocol_fini();
303310
xfrm6_policy_fini();

net/xfrm/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ endif
1313

1414
obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
1515
xfrm_input.o xfrm_output.o \
16-
xfrm_sysctl.o xfrm_replay.o xfrm_device.o
16+
xfrm_sysctl.o xfrm_replay.o xfrm_device.o \
17+
xfrm_nat_keepalive.o
1718
obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
1819
obj-$(CONFIG_XFRM_ALGO) += xfrm_algo.o
1920
obj-$(CONFIG_XFRM_USER) += xfrm_user.o

net/xfrm/xfrm_compat.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ static const struct nla_policy compat_policy[XFRMA_MAX+1] = {
129129
[XFRMA_SET_MARK_MASK] = { .type = NLA_U32 },
130130
[XFRMA_IF_ID] = { .type = NLA_U32 },
131131
[XFRMA_MTIMER_THRESH] = { .type = NLA_U32 },
132+
[XFRMA_NAT_KEEPALIVE_INTERVAL] = { .type = NLA_U32 },
132133
};
133134

134135
static struct nlmsghdr *xfrm_nlmsg_put_compat(struct sk_buff *skb,
@@ -277,9 +278,10 @@ static int xfrm_xlate64_attr(struct sk_buff *dst, const struct nlattr *src)
277278
case XFRMA_SET_MARK_MASK:
278279
case XFRMA_IF_ID:
279280
case XFRMA_MTIMER_THRESH:
281+
case XFRMA_NAT_KEEPALIVE_INTERVAL:
280282
return xfrm_nla_cpy(dst, src, nla_len(src));
281283
default:
282-
BUILD_BUG_ON(XFRMA_MAX != XFRMA_MTIMER_THRESH);
284+
BUILD_BUG_ON(XFRMA_MAX != XFRMA_NAT_KEEPALIVE_INTERVAL);
283285
pr_warn_once("unsupported nla_type %d\n", src->nla_type);
284286
return -EOPNOTSUPP;
285287
}
@@ -434,7 +436,7 @@ static int xfrm_xlate32_attr(void *dst, const struct nlattr *nla,
434436
int err;
435437

436438
if (type > XFRMA_MAX) {
437-
BUILD_BUG_ON(XFRMA_MAX != XFRMA_MTIMER_THRESH);
439+
BUILD_BUG_ON(XFRMA_MAX != XFRMA_NAT_KEEPALIVE_INTERVAL);
438440
NL_SET_ERR_MSG(extack, "Bad attribute");
439441
return -EOPNOTSUPP;
440442
}

0 commit comments

Comments
 (0)