linux-ppp.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH] ppp: add support for L2 multihop / tunnel switching
@ 2012-07-08 21:49 Benjamin LaHaise
  2012-07-09 11:52 ` James Chapman
  0 siblings, 1 reply; 5+ messages in thread
From: Benjamin LaHaise @ 2012-07-08 21:49 UTC (permalink / raw)
  To: netdev, linux-ppp

Hello folks,

Below is a first cut at implementing multihop L2TP, also known as tunnel 
switching.  The feature is similar in scope to how PPPoE relaying works -- 
L2 packets that are received on one PPP interface are forwarded to another.  
This feature is typically used for traffic aggregation and backhaul for 
ISPs, with incoming sessions (often PPPoE) being partially authenticated 
by a LAC, and then forwarded over an L2TP session to an LNS (selected by the 
user's domain) which then provides network access to the client.

This is an RFC primarily to get some feedback on the implementation 
approach being used.  At present, this code is intercepting packets as soon 
as they are received on a PPP channel.  The packets are then modified to 
use a fake ETH_P_PPP protocol type and sent out over another PPP device 
via dev_queue_xmit().  In theory this enables forwarding of any type of PPP 
session, although I've only tested L2TPv2 so far.

The reasoning behind using dev_queue_xmit() rather than outputting directly 
to another PPP channel is to enable the use of the traffic shaping and 
queuing features of the kernel on multihop sessions.

Comments / thoughts?  A sample test program is available at 
http://www.kvack.org/~bcrl/pppol2tp/multihop.c .  I am in the process of 
updating the Babylon PPP implementation to use this functionality, and 
expect to be ready to make those changes available later this week.  I 
have not yet finished testing this code, so I'm sure that there are bugs 
lurking within.

		-ben

Not-signed-off-yet-by: Benjamin LaHaise <bcrl@kvack.org>
---
 drivers/net/ppp/ppp_generic.c |   53 +++++++++++++++++++++++++++++++++++++++++-
 include/linux/if_ether.h      |    1 
 include/linux/ppp-ioctl.h     |    1 
 3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 5c05572..9c12712 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -121,6 +121,7 @@ struct ppp {
 	unsigned long	last_xmit;	/* jiffies when last pkt sent 9c */
 	unsigned long	last_recv;	/* jiffies when last pkt rcvd a0 */
 	struct net_device *dev;		/* network interface device a4 */
+	struct net_device *multihop_if;	/* if to forward incoming frames to */
 	int		closing;	/* is device closing down? a8 */
 #ifdef CONFIG_PPP_MULTILINK
 	int		nxchan;		/* next channel to send something on */
@@ -738,6 +739,30 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		err = 0;
 		break;
 
+	case PPPIOCSMULTIHOP_IF:
+	{
+		struct net_device *multihop_if;
+		if (get_user(val, p))
+			break;
+		err = 0;
+		if (ppp->multihop_if && (val = -1)) {
+			struct net_device *dev = ppp->multihop_if;
+			ppp->multihop_if = NULL;
+			dev_put(dev);
+			break;
+		}
+		err = -EBUSY;
+		if (ppp->multihop_if)
+			break;
+		multihop_if = dev_get_by_index(&init_net, val);
+		err = -ENOENT;
+		if (!multihop_if)
+			break;
+		ppp->multihop_if = multihop_if;
+		err = 0;
+		break;
+	}
+
 #ifdef CONFIG_PPP_FILTER
 	case PPPIOCSPASS:
 	{
@@ -942,6 +967,9 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	int npi, proto;
 	unsigned char *pp;
 
+	if (skb->protocol = htons(ETH_P_PPP))
+		goto queue;
+
 	npi = ethertype_to_npindex(ntohs(skb->protocol));
 	if (npi < 0)
 		goto outf;
@@ -968,6 +996,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	proto = npindex_to_proto[npi];
 	put_unaligned_be16(proto, pp);
 
+queue:
 	skb_queue_tail(&ppp->file.xq, skb);
 	ppp_xmit_process(ppp);
 	return NETDEV_TX_OK;
@@ -1131,6 +1160,9 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
 	int len;
 	unsigned char *cp;
 
+	if (skb->protocol = htons(ETH_P_PPP))
+		goto xmit;
+
 	if (proto < 0x8000) {
 #ifdef CONFIG_PPP_FILTER
 		/* check if we should pass this packet */
@@ -1228,6 +1260,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
 		return;
 	}
 
+xmit:
 	ppp->xmit_pending = skb;
 	ppp_push(ppp);
 	return;
@@ -1259,7 +1292,8 @@ ppp_push(struct ppp *ppp)
 		return;
 	}
 
-	if ((ppp->flags & SC_MULTILINK) = 0) {
+	if (((ppp->flags & SC_MULTILINK) = 0) ||
+	    (skb->protocol = htons(ETH_P_PPP))) {
 		/* not doing multilink: send it down the first channel */
 		list = list->next;
 		pch = list_entry(list, struct channel, clist);
@@ -1599,6 +1633,14 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
 		goto done;
 	}
 
+	if (pch->ppp && pch->ppp->multihop_if) {
+		skb->protocol = htons(ETH_P_PPP);
+		skb->dev = pch->ppp->multihop_if;
+		skb->ip_summed = CHECKSUM_NONE;
+		dev_queue_xmit(skb);
+		goto done;
+	}
+
 	proto = PPP_PROTO(skb);
 	if (!pch->ppp || proto >= 0xc000 || proto = PPP_CCPFRAG) {
 		/* put it on the channel queue */
@@ -2715,8 +2757,12 @@ static void ppp_shutdown_interface(struct ppp *ppp)
 	/* This will call dev_close() for us. */
 	ppp_lock(ppp);
 	if (!ppp->closing) {
+		struct net_device *multihop_if = ppp->multihop_if;
 		ppp->closing = 1;
+		ppp->multihop_if = NULL;
 		ppp_unlock(ppp);
+		if (multihop_if)
+			dev_put(multihop_if);
 		unregister_netdev(ppp->dev);
 		unit_put(&pn->units_idr, ppp->file.index);
 	} else
@@ -2764,6 +2810,11 @@ static void ppp_destroy_interface(struct ppp *ppp)
 #endif /* CONFIG_PPP_FILTER */
 
 	kfree_skb(ppp->xmit_pending);
+	printk("ppp_destroy_interface(%p): multihop_if = %p\n", ppp,
+		ppp->multihop_if);
+	if (ppp->multihop_if)
+		dev_put(ppp->multihop_if);
+	ppp->multihop_if = NULL;
 
 	free_netdev(ppp->dev);
 }
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 167ce5b..fe47a70 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -120,6 +120,7 @@
 #define ETH_P_PHONET	0x00F5		/* Nokia Phonet frames          */
 #define ETH_P_IEEE802154 0x00F6		/* IEEE802.15.4 frame		*/
 #define ETH_P_CAIF	0x00F7		/* ST-Ericsson CAIF protocol	*/
+#define ETH_P_PPP	0x00F8		/* Dummy type for PPP multihop	*/
 
 /*
  *	This is an Ethernet frame header.
diff --git a/include/linux/ppp-ioctl.h b/include/linux/ppp-ioctl.h
index 2d9a885..5571375 100644
--- a/include/linux/ppp-ioctl.h
+++ b/include/linux/ppp-ioctl.h
@@ -81,6 +81,7 @@ struct pppol2tp_ioc_stats {
  * Ioctl definitions.
  */
 
+#define	PPPIOCSMULTIHOP_IF	_IOWR('t', 91, int) /* set multihop if */
 #define	PPPIOCGFLAGS	_IOR('t', 90, int)	/* get configuration flags */
 #define	PPPIOCSFLAGS	_IOW('t', 89, int)	/* set configuration flags */
 #define	PPPIOCGASYNCMAP	_IOR('t', 88, int)	/* get async map */
-- 
"Thought is the essence of where you are now."

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] ppp: add support for L2 multihop / tunnel switching
  2012-07-08 21:49 [RFC PATCH] ppp: add support for L2 multihop / tunnel switching Benjamin LaHaise
@ 2012-07-09 11:52 ` James Chapman
  2012-07-09 14:15   ` Benjamin LaHaise
  0 siblings, 1 reply; 5+ messages in thread
From: James Chapman @ 2012-07-09 11:52 UTC (permalink / raw)
  To: Benjamin LaHaise; +Cc: netdev, linux-ppp

On 08/07/12 22:49, Benjamin LaHaise wrote:
> Hello folks,
> 
> Below is a first cut at implementing multihop L2TP, also known as tunnel 
> switching.  The feature is similar in scope to how PPPoE relaying works -- 
> L2 packets that are received on one PPP interface are forwarded to another.  
> This feature is typically used for traffic aggregation and backhaul for 
> ISPs, with incoming sessions (often PPPoE) being partially authenticated 
> by a LAC, and then forwarded over an L2TP session to an LNS (selected by the 
> user's domain) which then provides network access to the client.

As a mechanism for switching PPP interfaces together, this patch is
good. For L2TP though, I prefer an approach that would be applicable for
all L2TP traffic types, not just PPP.

L2TP supports many different pseudowire types, and this patch will only
be useful for tunnel switching between PPP pseudowires. Whereas if we
implement it within the L2TP core, rather than in the PPP code, we would
get switching between all pseudowire types. If we add this patch and
then subsequently add switching between other pseudowires in the L2TP
core (which we're likely to want to do), then we're left with two
different interfaces for doing L2TP tunnel switching in the kernel.

The L2TP core allows traffic to be passed directly into an L2TP session.
In the case of PPPoE, for example, the PPP data can be  extracted from a
PPPoE packet and passed into an L2TP tunnel/session, with no PPP
interface(s) involved.

That said, your approach allows two PPP interfaces to be switched
together, which has its own advantages.

> The reasoning behind using dev_queue_xmit() rather than outputting directly 
> to another PPP channel is to enable the use of the traffic shaping and 
> queuing features of the kernel on multihop sessions.

I'm not sure about using a pseudo packet type to do this. For L2TP, it
would seem better to add netfilter/tc support for L2TP data packets,
which would let people add rules for, say, traffic in L2TP tunnel x /
session y. This would avoid the need for ETH_P_PPP and you could then
output directly to the ppp channel.


-- 
James Chapman
Katalix Systems Ltd
http://www.katalix.com
Catalysts for your Embedded Linux software development



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] ppp: add support for L2 multihop / tunnel switching
  2012-07-09 11:52 ` James Chapman
@ 2012-07-09 14:15   ` Benjamin LaHaise
  2012-07-10  3:27     ` [RFC PATCH v2 net-next] " Benjamin LaHaise
  2012-07-10  9:32     ` James Chapman
  0 siblings, 2 replies; 5+ messages in thread
From: Benjamin LaHaise @ 2012-07-09 14:15 UTC (permalink / raw)
  To: James Chapman; +Cc: netdev, linux-ppp

On Mon, Jul 09, 2012 at 12:52:15PM +0100, James Chapman wrote:
> As a mechanism for switching PPP interfaces together, this patch is
> good. For L2TP though, I prefer an approach that would be applicable for
> all L2TP traffic types, not just PPP.

*nod*  This seems like a reasonable consideration.

> L2TP supports many different pseudowire types, and this patch will only
> be useful for tunnel switching between PPP pseudowires. Whereas if we
> implement it within the L2TP core, rather than in the PPP code, we would
> get switching between all pseudowire types. If we add this patch and
> then subsequently add switching between other pseudowires in the L2TP
> core (which we're likely to want to do), then we're left with two
> different interfaces for doing L2TP tunnel switching in the kernel.

At least for ethernet pseudowires, it can already be implemented by using 
an ethernet bridge device.  Besides PPP and ethernet pseudowires, what 
other types are supported at present by the L2TP core?

> The L2TP core allows traffic to be passed directly into an L2TP session.
> In the case of PPPoE, for example, the PPP data can be  extracted from a
> PPPoE packet and passed into an L2TP tunnel/session, with no PPP
> interface(s) involved.
> 
> That said, your approach allows two PPP interfaces to be switched
> together, which has its own advantages.

I think the approach I'm using should be reasonably efficient for PPPoE 
to L2TP, although the locking overhead in the PPP core probably needs to 
be reduced to improve scaling.  I haven't yet done any benchmarking on this 
approach to see how much overhead there is compared to the other code I'd 
written which took a more direct approach (this wasn't on top of the 
ppp_generic core, but the old Babylon kernel modules which have had this 
functionality for a long time).

> > The reasoning behind using dev_queue_xmit() rather than outputting directly 
> > to another PPP channel is to enable the use of the traffic shaping and 
> > queuing features of the kernel on multihop sessions.
> 
> I'm not sure about using a pseudo packet type to do this. For L2TP, it
> would seem better to add netfilter/tc support for L2TP data packets,
> which would let people add rules for, say, traffic in L2TP tunnel x /
> session y. This would avoid the need for ETH_P_PPP and you could then
> output directly to the ppp channel.

The downside of an L2TP specific method is that all the mechanisms need to 
be duplicated, resulting in a much higher maintenance overhead for the 
code and functionality, not to mention all the tool changes to go along 
with that.

As for the pseudo packet type, it may indeed be better to avoid the pseudo 
packet type for known PPP packet types.  One of the benefits of going the 
network device route is that it makes it much easier to implement additional 
functionality like lawful intercept, which would be yet more functionality 
that would have to be implemented if the mechanism is L2TP specific.  The 
pseudo packet type would still be needed for forwarding PPP frames that the 
kernel doesn't know about (all the *CP packet types and MLPPP come to mind)

I had thought about doing the packet forwarding in a manner similar to the 
bridging code -- that is, as a pseudowire bridge in the network core that 
only works between 2 devices.  That approach might work better for L2TP, as 
it would be able to pass packets of any type between the 2 endpoints.

		-ben
-- 
"Thought is the essence of where you are now."

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [RFC PATCH v2 net-next] Re: [RFC PATCH] ppp: add support for L2 multihop / tunnel switching
  2012-07-09 14:15   ` Benjamin LaHaise
@ 2012-07-10  3:27     ` Benjamin LaHaise
  2012-07-10  9:32     ` James Chapman
  1 sibling, 0 replies; 5+ messages in thread
From: Benjamin LaHaise @ 2012-07-10  3:27 UTC (permalink / raw)
  To: James Chapman; +Cc: netdev, linux-ppp

Hello all,

Here is v2 of the PPP multihop patch.  This version adds a notifier hook to 
make sure that the multihop reference is dropped when the multihop target 
gets unregistered, ensuring that the references are properly dropped witout 
leaking the devices.

		-ben

Not-yet-signed-off-by: Benjamin LaHaise <bcrl@kvack.org>
 drivers/net/ppp/ppp_generic.c |  119 ++++++++++++++++++++++++++++++++++++++++--
 include/linux/if_ether.h      |    1 
 include/linux/ppp-ioctl.h     |    1 
 3 files changed, 118 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 5c05572..6dc7eff 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -121,6 +121,7 @@ struct ppp {
 	unsigned long	last_xmit;	/* jiffies when last pkt sent 9c */
 	unsigned long	last_recv;	/* jiffies when last pkt rcvd a0 */
 	struct net_device *dev;		/* network interface device a4 */
+	struct net_device *multihop_if;	/* if to forward incoming frames to */
 	int		closing;	/* is device closing down? a8 */
 #ifdef CONFIG_PPP_MULTILINK
 	int		nxchan;		/* next channel to send something on */
@@ -272,6 +273,7 @@ static void unit_put(struct idr *p, int n);
 static void *unit_find(struct idr *p, int n);
 
 static struct class *ppp_class;
+static const struct net_device_ops ppp_netdev_ops;
 
 /* per net-namespace data */
 static inline struct ppp_net *ppp_pernet(struct net *net)
@@ -380,8 +382,9 @@ static int ppp_release(struct inode *unused, struct file *file)
 		file->private_data = NULL;
 		if (pf->kind = INTERFACE) {
 			ppp = PF_TO_PPP(pf);
-			if (file = ppp->owner)
+			if (file = ppp->owner) {
 				ppp_shutdown_interface(ppp);
+			}
 		}
 		if (atomic_dec_and_test(&pf->refcnt)) {
 			switch (pf->kind) {
@@ -553,6 +556,41 @@ static int get_filter(void __user *arg, struct sock_filter **p)
 }
 #endif /* CONFIG_PPP_FILTER */
 
+static int ppp_multihop_event(struct notifier_block *this, unsigned long event,
+			      void *ptr)
+{
+	struct net_device *event_dev = (struct net_device *)ptr;
+	struct net_device *master = event_dev->master;
+	struct ppp *ppp;
+
+	if (event_dev->netdev_ops != &ppp_netdev_ops)
+		return NOTIFY_DONE;
+	if (!master || (master->netdev_ops != &ppp_netdev_ops))
+		return NOTIFY_DONE;
+
+	ppp = netdev_priv(master);
+
+	switch (event) {
+	case NETDEV_UNREGISTER:
+		ppp_lock(ppp);
+		BUG_ON(ppp->multihop_if != event_dev);
+		ppp->multihop_if = NULL;
+		netdev_set_master(event_dev, NULL);
+		ppp_unlock(ppp);
+		dev_put(event_dev);
+		break;
+
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ppp_multihop_notifier = {
+	.notifier_call = ppp_multihop_event,
+};
+
 static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct ppp_file *pf = file->private_data;
@@ -738,6 +776,46 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		err = 0;
 		break;
 
+	case PPPIOCSMULTIHOP_IF:
+	{
+		struct net_device *multihop_if;
+		if (get_user(val, p))
+			break;
+		rtnl_lock();
+		ppp_lock(ppp);
+		err = 0;
+		multihop_if = ppp->multihop_if;
+		if (multihop_if && (val = -1)) {
+			ppp->multihop_if = NULL;
+			BUG_ON(multihop_if->master != ppp->dev);
+			netdev_set_master(multihop_if, NULL);
+			goto out_multihop;
+		}
+		err = -EBUSY;
+		multihop_if = NULL;
+		if (ppp->multihop_if)
+			goto out_multihop;
+		multihop_if = dev_get_by_index(&init_net, val);
+		err = -ENOENT;
+		if (!multihop_if)
+			goto out_multihop;
+		err = -EINVAL;
+		if (multihop_if->netdev_ops != &ppp_netdev_ops)
+			goto out_multihop;
+		err = netdev_set_master(multihop_if, ppp->dev);
+		if (err)
+			goto out_multihop;
+		ppp->multihop_if = multihop_if;
+		multihop_if = NULL;
+		err = 0;
+out_multihop:
+		ppp_unlock(ppp);
+		rtnl_unlock();
+		if (multihop_if)
+			dev_put(multihop_if);
+		break;
+	}
+
 #ifdef CONFIG_PPP_FILTER
 	case PPPIOCSPASS:
 	{
@@ -901,6 +979,7 @@ static int __init ppp_init(void)
 
 	pr_info("PPP generic driver version " PPP_VERSION "\n");
 
+	register_netdevice_notifier(&ppp_multihop_notifier);
 	err = register_pernet_device(&ppp_net_ops);
 	if (err) {
 		pr_err("failed to register PPP pernet device (%d)\n", err);
@@ -942,6 +1021,9 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	int npi, proto;
 	unsigned char *pp;
 
+	if (skb->protocol = htons(ETH_P_PPP))
+		goto queue;
+
 	npi = ethertype_to_npindex(ntohs(skb->protocol));
 	if (npi < 0)
 		goto outf;
@@ -968,6 +1050,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	proto = npindex_to_proto[npi];
 	put_unaligned_be16(proto, pp);
 
+queue:
 	skb_queue_tail(&ppp->file.xq, skb);
 	ppp_xmit_process(ppp);
 	return NETDEV_TX_OK;
@@ -1131,6 +1214,9 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
 	int len;
 	unsigned char *cp;
 
+	if (skb->protocol = htons(ETH_P_PPP))
+		goto xmit;
+
 	if (proto < 0x8000) {
 #ifdef CONFIG_PPP_FILTER
 		/* check if we should pass this packet */
@@ -1228,6 +1314,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
 		return;
 	}
 
+xmit:
 	ppp->xmit_pending = skb;
 	ppp_push(ppp);
 	return;
@@ -1259,7 +1346,8 @@ ppp_push(struct ppp *ppp)
 		return;
 	}
 
-	if ((ppp->flags & SC_MULTILINK) = 0) {
+	if (((ppp->flags & SC_MULTILINK) = 0) ||
+	    (skb->protocol = htons(ETH_P_PPP))) {
 		/* not doing multilink: send it down the first channel */
 		list = list->next;
 		pch = list_entry(list, struct channel, clist);
@@ -1599,6 +1687,14 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
 		goto done;
 	}
 
+	if (pch->ppp && pch->ppp->multihop_if) {
+		skb->protocol = htons(ETH_P_PPP);
+		skb->dev = pch->ppp->multihop_if;
+		skb->ip_summed = CHECKSUM_NONE;
+		dev_queue_xmit(skb);
+		goto done;
+	}
+
 	proto = PPP_PROTO(skb);
 	if (!pch->ppp || proto >= 0xc000 || proto = PPP_CCPFRAG) {
 		/* put it on the channel queue */
@@ -2709,18 +2805,28 @@ static void ppp_shutdown_interface(struct ppp *ppp)
 {
 	struct ppp_net *pn;
 
+	rtnl_lock();
 	pn = ppp_pernet(ppp->ppp_net);
 	mutex_lock(&pn->all_ppp_mutex);
 
 	/* This will call dev_close() for us. */
 	ppp_lock(ppp);
 	if (!ppp->closing) {
+		struct net_device *multihop_if = ppp->multihop_if;
 		ppp->closing = 1;
+		ppp->multihop_if = NULL;
 		ppp_unlock(ppp);
+		if (multihop_if)
+			netdev_set_master(multihop_if, NULL);
+		rtnl_unlock();
 		unregister_netdev(ppp->dev);
 		unit_put(&pn->units_idr, ppp->file.index);
-	} else
+		if (multihop_if)
+			dev_put(multihop_if);
+	} else {
 		ppp_unlock(ppp);
+		rtnl_unlock();
+	}
 
 	ppp->file.dead = 1;
 	ppp->owner = NULL;
@@ -2764,6 +2870,12 @@ static void ppp_destroy_interface(struct ppp *ppp)
 #endif /* CONFIG_PPP_FILTER */
 
 	kfree_skb(ppp->xmit_pending);
+	if (ppp->multihop_if) {
+		struct net_device *multihop_if = ppp->multihop_if;
+		ppp->multihop_if = NULL;
+		netdev_set_master(multihop_if, NULL);
+		dev_put(multihop_if);
+	}
 
 	free_netdev(ppp->dev);
 }
@@ -2901,6 +3013,7 @@ static void __exit ppp_cleanup(void)
 	device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
 	class_destroy(ppp_class);
 	unregister_pernet_device(&ppp_net_ops);
+	unregister_netdevice_notifier(&ppp_multihop_notifier);
 }
 
 /*
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 167ce5b..fe47a70 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -120,6 +120,7 @@
 #define ETH_P_PHONET	0x00F5		/* Nokia Phonet frames          */
 #define ETH_P_IEEE802154 0x00F6		/* IEEE802.15.4 frame		*/
 #define ETH_P_CAIF	0x00F7		/* ST-Ericsson CAIF protocol	*/
+#define ETH_P_PPP	0x00F8		/* Dummy type for PPP multihop	*/
 
 /*
  *	This is an Ethernet frame header.
diff --git a/include/linux/ppp-ioctl.h b/include/linux/ppp-ioctl.h
index 2d9a885..5571375 100644
--- a/include/linux/ppp-ioctl.h
+++ b/include/linux/ppp-ioctl.h
@@ -81,6 +81,7 @@ struct pppol2tp_ioc_stats {
  * Ioctl definitions.
  */
 
+#define	PPPIOCSMULTIHOP_IF	_IOWR('t', 91, int) /* set multihop if */
 #define	PPPIOCGFLAGS	_IOR('t', 90, int)	/* get configuration flags */
 #define	PPPIOCSFLAGS	_IOW('t', 89, int)	/* set configuration flags */
 #define	PPPIOCGASYNCMAP	_IOR('t', 88, int)	/* get async map */

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] ppp: add support for L2 multihop / tunnel switching
  2012-07-09 14:15   ` Benjamin LaHaise
  2012-07-10  3:27     ` [RFC PATCH v2 net-next] " Benjamin LaHaise
@ 2012-07-10  9:32     ` James Chapman
  1 sibling, 0 replies; 5+ messages in thread
From: James Chapman @ 2012-07-10  9:32 UTC (permalink / raw)
  To: Benjamin LaHaise; +Cc: netdev, linux-ppp

On 09/07/12 15:15, Benjamin LaHaise wrote:
> On Mon, Jul 09, 2012 at 12:52:15PM +0100, James Chapman wrote:
>> As a mechanism for switching PPP interfaces together, this patch is
>> good. For L2TP though, I prefer an approach that would be applicable for
>> all L2TP traffic types, not just PPP.
> 
> *nod*  This seems like a reasonable consideration.
> 
>> L2TP supports many different pseudowire types, and this patch will only
>> be useful for tunnel switching between PPP pseudowires. Whereas if we
>> implement it within the L2TP core, rather than in the PPP code, we would
>> get switching between all pseudowire types. If we add this patch and
>> then subsequently add switching between other pseudowires in the L2TP
>> core (which we're likely to want to do), then we're left with two
>> different interfaces for doing L2TP tunnel switching in the kernel.
> 
> At least for ethernet pseudowires, it can already be implemented by using 
> an ethernet bridge device.  Besides PPP and ethernet pseudowires, what 
> other types are supported at present by the L2TP core?

Only those two at the moment, but others (ATM etc) can be added if and
when there is demand. To do this at an L2TP level avoids using two
linked PPP interfaces in the case of PPP and two bridged l2tpeth
interfaces in the case of ethernet. I envisage a new L2TP netlink API to
join the datapaths of two L2TP sessions together with no devices being
needed. It would work for all L2TP session types, now and in the future.

>>> The reasoning behind using dev_queue_xmit() rather than outputting directly 
>>> to another PPP channel is to enable the use of the traffic shaping and 
>>> queuing features of the kernel on multihop sessions.
>>
>> I'm not sure about using a pseudo packet type to do this. For L2TP, it
>> would seem better to add netfilter/tc support for L2TP data packets,
>> which would let people add rules for, say, traffic in L2TP tunnel x /
>> session y. This would avoid the need for ETH_P_PPP and you could then
>> output directly to the ppp channel.
> 
> The downside of an L2TP specific method is that all the mechanisms need to 
> be duplicated, resulting in a much higher maintenance overhead for the 
> code and functionality, not to mention all the tool changes to go along 
> with that.

Could the same argument be applied to other protocols which have
netfilter/tc support already? Adding support for L2TP would seem
consistent with other protocol implementations. It would also mean that
the same rules would work for all L2TP session types.

> As for the pseudo packet type, it may indeed be better to avoid the pseudo 
> packet type for known PPP packet types.  One of the benefits of going the 
> network device route is that it makes it much easier to implement additional 
> functionality like lawful intercept, which would be yet more functionality 
> that would have to be implemented if the mechanism is L2TP specific.  The 
> pseudo packet type would still be needed for forwarding PPP frames that the 
> kernel doesn't know about (all the *CP packet types and MLPPP come to mind)
> 
> I had thought about doing the packet forwarding in a manner similar to the 
> bridging code -- that is, as a pseudowire bridge in the network core that 
> only works between 2 devices.  That approach might work better for L2TP, as 
> it would be able to pass packets of any type between the 2 endpoints.

For L2TP, I think it should be possible to avoid having devices for
switched L2TP sessions.

> 
> 		-ben
> 
-- 
James Chapman
Katalix Systems Ltd
http://www.katalix.com
Catalysts for your Embedded Linux software development



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-07-10  9:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-08 21:49 [RFC PATCH] ppp: add support for L2 multihop / tunnel switching Benjamin LaHaise
2012-07-09 11:52 ` James Chapman
2012-07-09 14:15   ` Benjamin LaHaise
2012-07-10  3:27     ` [RFC PATCH v2 net-next] " Benjamin LaHaise
2012-07-10  9:32     ` James Chapman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).