@@ -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
*****************************************************************************/
@@ -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.
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(+)