diff mbox series

[RFC,net-next,2/3] net/l2tp: add flow-based session create API

Message ID 20210929094514.15048-3-tparkin@katalix.com (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series support "flow-based" datapath in l2tp | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Clearly marked for net-next
netdev/subject_prefix success Link
netdev/cc_maintainers warning 8 maintainers not CCed: mschiffer@universe-factory.net xiyuyang19@fudan.edu.cn kuba@kernel.org unixbhaskar@gmail.com xiongx18@fudan.edu.cn davem@davemloft.net sishuai@purdue.edu tanxin.ctf@gmail.com
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch warning WARNING: line length of 83 exceeds 80 columns WARNING: line length of 91 exceeds 80 columns
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/header_inline success Link

Commit Message

Tom Parkin Sept. 29, 2021, 9:45 a.m. UTC
In order to support multiple logical sessions over a single L2TP tunnel
virtual netdev, the L2TP session creation API needs to be extended.  The
new "flow-based" sessions will not create a virtual net device
per-session, but instead will use tc rules and tunnel metadata to direct
traffic:

        tc qdisc add dev l2tpt1 handle ffff: ingress
        tc filter add dev l2tpt1 parent ffff: flower enc_key_id 1 \
                action mirred egress redirect dev eth0

To allow this session type to co-exist with the existing pseudowire
types, define a new API for creating flow-based sessions which the
l2tp netlink code can call directly.

Signed-off-by: Tom Parkin <tparkin@katalix.com>
---
 net/l2tp/l2tp_core.c | 46 ++++++++++++++++++++++++++++++++++++++++++++
 net/l2tp/l2tp_core.h |  8 ++++++++
 2 files changed, 54 insertions(+)
diff mbox series

Patch

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 6a4d3d785c65..dd0b1d64fd14 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1661,6 +1661,52 @@  struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn
 }
 EXPORT_SYMBOL_GPL(l2tp_session_create);
 
+static void l2tp_flow_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len)
+{
+	struct metadata_dst *mdst;
+	__be64 id;
+
+	if (!session->tunnel->dev)
+		goto drop;
+
+	id = key32_to_tunnel_id(htonl(session->session_id));
+
+	mdst = ip_tun_rx_dst(skb, TUNNEL_KEY, id, sizeof(*mdst));
+	if (!mdst)
+		goto drop;
+
+	skb->skb_iif = skb->dev->ifindex;
+	skb->dev = session->tunnel->dev;
+	skb_dst_set(skb, (struct dst_entry *)mdst);
+	skb_reset_mac_header(skb);
+	netif_receive_skb(skb);
+	return;
+
+drop:
+	kfree_skb(skb);
+}
+
+int l2tp_flow_session_create(struct l2tp_tunnel *tunnel,
+			     u32 session_id, u32 peer_session_id,
+			     struct l2tp_session_cfg *cfg)
+{
+	struct l2tp_session *session;
+	int ret;
+
+	session = l2tp_session_create(0, tunnel, session_id, peer_session_id, cfg);
+	if (IS_ERR(session)) {
+		ret = PTR_ERR(session);
+		goto out;
+	}
+
+	session->recv_skb = l2tp_flow_recv;
+
+	ret = l2tp_session_register(session, tunnel);
+out:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(l2tp_flow_session_create);
+
 /*****************************************************************************
  * Tunnel virtual netdev
  *****************************************************************************/
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 4d2aeb852f38..1a0b9859a7e1 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -252,6 +252,14 @@  int l2tp_session_register(struct l2tp_session *session,
 			  struct l2tp_tunnel *tunnel);
 void l2tp_session_delete(struct l2tp_session *session);
 
+/* Flow-based session.
+ * Optimised datapath which doesn't require a netdev per session instance
+ * and which is managed from userspace using tc rules.
+ */
+int l2tp_flow_session_create(struct l2tp_tunnel *tunnel,
+			     u32 session_id, u32 peer_session_id,
+			     struct l2tp_session_cfg *cfg);
+
 /* Receive path helpers.  If data sequencing is enabled for the session these
  * functions handle queuing and reordering prior to passing packets to the
  * pseudowire code to be passed to userspace.