From: Eyal Birger <eyal.birger@gmail.com>
To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, steffen.klassert@secunet.com,
herbert@gondor.apana.org.au, pablo@netfilter.org,
contact@proelbtn.com, dsahern@kernel.org
Cc: netdev@vger.kernel.org, bpf@vger.kernel.org,
devel@linux-ipsec.org, Eyal Birger <eyal.birger@gmail.com>
Subject: [PATCH ipsec-next 3/3] xfrm: lwtunnel: add lwtunnel support for xfrm interfaces in collect_md mode
Date: Tue, 23 Aug 2022 18:45:57 +0300 [thread overview]
Message-ID: <20220823154557.1400380-4-eyal.birger@gmail.com> (raw)
In-Reply-To: <20220823154557.1400380-1-eyal.birger@gmail.com>
Allow specifying the xfrm interface if_id as part of a route metadata
using the lwtunnel infrastructure.
This allows for example using a single xfrm interface in collect_md
mode as the target of multiple routes each specifying a different if_id.
With the appropriate changes to iproute2, considering an xfrm device
ipsec1 in collect_md mode one can for example add a route specifying
an if_id like so:
ip route add <SUBNET> dev ipsec1 encap xfrm if_id 1
In which case traffic routed to the device via this route would use
if_id in the xfrm interface policy lookup.
Signed-off-by: Eyal Birger <eyal.birger@gmail.com>
---
include/net/dst_metadata.h | 6 +++
include/uapi/linux/lwtunnel.h | 9 ++++
net/core/lwtunnel.c | 1 +
net/xfrm/xfrm_interface.c | 88 +++++++++++++++++++++++++++++++++++
4 files changed, 104 insertions(+)
diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h
index 7e13210b868f..122066595966 100644
--- a/include/net/dst_metadata.h
+++ b/include/net/dst_metadata.h
@@ -62,10 +62,16 @@ skb_tunnel_info(const struct sk_buff *skb)
static inline struct xfrm_md_info *skb_xfrm_md_info(const struct sk_buff *skb)
{
struct metadata_dst *md_dst = skb_metadata_dst(skb);
+ struct dst_entry *dst;
if (md_dst && md_dst->type == METADATA_XFRM)
return &md_dst->u.xfrm_info;
+ dst = skb_dst(skb);
+ if (dst && dst->lwtstate &&
+ dst->lwtstate->type == LWTUNNEL_ENCAP_XFRM)
+ return (struct xfrm_md_info *)dst->lwtstate->data;
+
return NULL;
}
diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h
index 2e206919125c..d26bace86332 100644
--- a/include/uapi/linux/lwtunnel.h
+++ b/include/uapi/linux/lwtunnel.h
@@ -15,6 +15,7 @@ enum lwtunnel_encap_types {
LWTUNNEL_ENCAP_SEG6_LOCAL,
LWTUNNEL_ENCAP_RPL,
LWTUNNEL_ENCAP_IOAM6,
+ LWTUNNEL_ENCAP_XFRM,
__LWTUNNEL_ENCAP_MAX,
};
@@ -111,4 +112,12 @@ enum {
#define LWT_BPF_MAX_HEADROOM 256
+enum {
+ LWT_XFRM_UNSPEC,
+ LWT_XFRM_IF_ID,
+ __LWT_XFRM_MAX,
+};
+
+#define LWT_XFRM_MAX (__LWT_XFRM_MAX - 1)
+
#endif /* _UAPI_LWTUNNEL_H_ */
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index 9ccd64e8a666..6fac2f0ef074 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -50,6 +50,7 @@ static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type)
return "IOAM6";
case LWTUNNEL_ENCAP_IP6:
case LWTUNNEL_ENCAP_IP:
+ case LWTUNNEL_ENCAP_XFRM:
case LWTUNNEL_ENCAP_NONE:
case __LWTUNNEL_ENCAP_MAX:
/* should not have got here */
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index efb8263e1c22..9f0a5cc2895d 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -60,6 +60,91 @@ struct xfrmi_net {
struct xfrm_if __rcu *collect_md_xfrmi;
};
+static inline struct xfrm_md_info *xfrm_lwt(struct lwtunnel_state *lwt)
+{
+ return (struct xfrm_md_info *)lwt->data;
+}
+
+static const struct nla_policy xfrm_lwt_policy[LWT_XFRM_MAX + 1] = {
+ [LWT_XFRM_UNSPEC] = { .type = NLA_REJECT },
+ [LWT_XFRM_IF_ID] = { .type = NLA_U32 },
+};
+
+static void xfrmi_destroy_state(struct lwtunnel_state *lwt)
+{
+}
+
+static int xfrmi_build_state(struct net *net, struct nlattr *nla,
+ unsigned int family, const void *cfg,
+ struct lwtunnel_state **ts,
+ struct netlink_ext_ack *extack)
+{
+ struct nlattr *tb[LWT_XFRM_MAX + 1];
+ struct lwtunnel_state *new_state;
+ struct xfrm_md_info *info;
+ int ret;
+
+ ret = nla_parse_nested(tb, LWT_XFRM_MAX, nla, xfrm_lwt_policy, extack);
+ if (ret < 0)
+ return ret;
+
+ if (!tb[LWT_XFRM_IF_ID])
+ return -EINVAL;
+
+ new_state = lwtunnel_state_alloc(sizeof(*info));
+ if (!new_state)
+ return -ENOMEM;
+
+ new_state->type = LWTUNNEL_ENCAP_XFRM;
+
+ info = xfrm_lwt(new_state);
+ info->if_id = nla_get_u32(tb[LWT_XFRM_IF_ID]);
+ if (!info->if_id) {
+ ret = -EINVAL;
+ goto errout;
+ }
+ *ts = new_state;
+ return 0;
+
+errout:
+ xfrmi_destroy_state(new_state);
+ kfree(new_state);
+ return ret;
+}
+
+static int xfrmi_fill_encap_info(struct sk_buff *skb,
+ struct lwtunnel_state *lwt)
+{
+ struct xfrm_md_info *info = xfrm_lwt(lwt);
+
+ if (nla_put_u32(skb, LWT_XFRM_IF_ID, info->if_id))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int xfrmi_encap_nlsize(struct lwtunnel_state *lwtstate)
+{
+ return nla_total_size(4); /* LWT_XFRM_IF_ID */
+}
+
+static int xfrmi_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
+{
+ struct xfrm_md_info *a_info = xfrm_lwt(a);
+ struct xfrm_md_info *b_info = xfrm_lwt(b);
+
+ return memcmp(a_info, b_info, sizeof(*a_info));
+}
+
+static const struct lwtunnel_encap_ops xfrmi_encap_ops = {
+ .build_state = xfrmi_build_state,
+ .destroy_state = xfrmi_destroy_state,
+ .fill_encap = xfrmi_fill_encap_info,
+ .get_encap_size = xfrmi_encap_nlsize,
+ .cmp_encap = xfrmi_encap_cmp,
+ .owner = THIS_MODULE,
+};
+
#define for_each_xfrmi_rcu(start, xi) \
for (xi = rcu_dereference(start); xi; xi = rcu_dereference(xi->next))
@@ -1076,6 +1161,8 @@ static int __init xfrmi_init(void)
if (err < 0)
goto rtnl_link_failed;
+ lwtunnel_encap_add_ops(&xfrmi_encap_ops, LWTUNNEL_ENCAP_XFRM);
+
xfrm_if_register_cb(&xfrm_if_cb);
return err;
@@ -1094,6 +1181,7 @@ static int __init xfrmi_init(void)
static void __exit xfrmi_fini(void)
{
xfrm_if_unregister_cb();
+ lwtunnel_encap_del_ops(&xfrmi_encap_ops, LWTUNNEL_ENCAP_XFRM);
rtnl_link_unregister(&xfrmi_link_ops);
xfrmi4_fini();
xfrmi6_fini();
--
2.34.1
next prev parent reply other threads:[~2022-08-23 17:49 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-23 15:45 [PATCH ipsec-next 0/3] xfrm: support collect metadata mode for xfrm interfaces Eyal Birger
2022-08-23 15:45 ` [PATCH ipsec-next 1/3] net: allow storing xfrm interface metadata in metadata_dst Eyal Birger
2022-08-23 15:45 ` [PATCH ipsec-next 2/3] xfrm: interface: support collect metadata mode Eyal Birger
2022-08-24 17:06 ` Daniel Borkmann
2022-08-24 18:25 ` Eyal Birger
2022-08-24 21:33 ` Daniel Borkmann
2022-08-23 15:45 ` Eyal Birger [this message]
2022-08-24 15:21 ` [PATCH ipsec-next 3/3] xfrm: lwtunnel: add lwtunnel support for xfrm interfaces in collect_md mode Nicolas Dichtel
2022-08-24 18:56 ` Eyal Birger
2022-08-25 10:07 ` Nicolas Dichtel
2022-08-25 13:03 ` Eyal Birger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220823154557.1400380-4-eyal.birger@gmail.com \
--to=eyal.birger@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=contact@proelbtn.com \
--cc=davem@davemloft.net \
--cc=devel@linux-ipsec.org \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=herbert@gondor.apana.org.au \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pablo@netfilter.org \
--cc=steffen.klassert@secunet.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox