[RFC PATCH net-next 2/3] net/l2tp: add flow-based session create API
From: Tom Parkin <hidden>
Date: 2021-09-29 09:45:35
Subsystem:
networking [general], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
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 <redacted>
---
net/l2tp/l2tp_core.c | 46 ++++++++++++++++++++++++++++++++++++++++++++
net/l2tp/l2tp_core.h | 8 ++++++++
2 files changed, 54 insertions(+)
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.
--
2.17.1