Updated PPPoE,PPTP,L2TP and GRE patches.

Source: codelinaro.org
This commit is contained in:
SqTER-PL
2025-03-16 12:09:03 +01:00
committed by Lucas Asvio
parent f35f4f6dbd
commit ddf1e90667
25 changed files with 1800 additions and 1391 deletions

View File

@@ -90,7 +90,7 @@
{
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4701,6 +4701,15 @@ void dev_uc_flush(struct net_device *dev
@@ -4681,6 +4681,15 @@ void dev_uc_flush(struct net_device *dev
void dev_uc_init(struct net_device *dev);
/**

View File

@@ -105,7 +105,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
static inline __be16 vlan_proto(const struct sk_buff *skb)
{
if (skb_vlan_tag_present(skb))
@@ -1238,6 +1247,12 @@ static struct ctl_table brnf_table[] = {
@@ -1240,6 +1249,12 @@ static struct ctl_table brnf_table[] = {
.mode = 0644,
.proc_handler = brnf_sysctl_call_tables,
},
@@ -118,7 +118,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
{ }
};
@@ -1246,6 +1261,7 @@ static inline void br_netfilter_sysctl_d
@@ -1248,6 +1263,7 @@ static inline void br_netfilter_sysctl_d
brnf->call_iptables = 1;
brnf->call_ip6tables = 1;
brnf->call_arptables = 1;
@@ -126,7 +126,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
brnf->filter_vlan_tagged = 0;
brnf->filter_pppoe_tagged = 0;
brnf->pass_vlan_indev = 0;
@@ -1269,6 +1285,7 @@ static int br_netfilter_sysctl_init_net(
@@ -1271,6 +1287,7 @@ static int br_netfilter_sysctl_init_net(
table[3].data = &brnet->filter_vlan_tagged;
table[4].data = &brnet->filter_pppoe_tagged;
table[5].data = &brnet->pass_vlan_indev;

View File

@@ -15,7 +15,7 @@ Signed-off-by: Ken Zhu <quic_guigenz@quicinc.com>
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3183,6 +3183,8 @@ static inline int dev_direct_xmit(struct
@@ -3163,6 +3163,8 @@ static inline int dev_direct_xmit(struct
return ret;
}

View File

@@ -37,7 +37,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
const struct dst_entry *dst = skb_dst(skb);
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -237,6 +237,9 @@ struct rtable *rt_dst_alloc(struct net_d
@@ -238,6 +238,9 @@ struct rtable *rt_dst_alloc(struct net_d
unsigned int flags, u16 type, bool noxfrm);
struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt);

View File

@@ -18,7 +18,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2959,6 +2959,8 @@ enum netdev_cmd {
@@ -2939,6 +2939,8 @@ enum netdev_cmd {
NETDEV_OFFLOAD_XSTATS_REPORT_USED,
NETDEV_OFFLOAD_XSTATS_REPORT_DELTA,
NETDEV_XDP_FEAT_CHANGE,

View File

@@ -35,7 +35,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
}
static inline __be16 vlan_proto(const struct sk_buff *skb)
@@ -1253,6 +1254,12 @@ static struct ctl_table brnf_table[] = {
@@ -1255,6 +1256,12 @@ static struct ctl_table brnf_table[] = {
.mode = 0644,
.proc_handler = brnf_sysctl_call_tables,
},
@@ -48,7 +48,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
{ }
};
@@ -1262,6 +1269,7 @@ static inline void br_netfilter_sysctl_d
@@ -1264,6 +1271,7 @@ static inline void br_netfilter_sysctl_d
brnf->call_ip6tables = 1;
brnf->call_arptables = 1;
brnf->call_ebtables = 1;
@@ -56,7 +56,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
brnf->filter_vlan_tagged = 0;
brnf->filter_pppoe_tagged = 0;
brnf->pass_vlan_indev = 0;
@@ -1286,6 +1294,7 @@ static int br_netfilter_sysctl_init_net(
@@ -1288,6 +1296,7 @@ static int br_netfilter_sysctl_init_net(
table[4].data = &brnet->filter_pppoe_tagged;
table[5].data = &brnet->pass_vlan_indev;
table[6].data = &brnet->call_ebtables;

View File

@@ -14,7 +14,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -1268,8 +1268,8 @@ static inline void br_netfilter_sysctl_d
@@ -1270,8 +1270,8 @@ static inline void br_netfilter_sysctl_d
brnf->call_iptables = 1;
brnf->call_ip6tables = 1;
brnf->call_arptables = 1;

View File

@@ -54,7 +54,7 @@ Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
dev->needs_free_netdev = true;
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1781,6 +1781,32 @@ enum netdev_priv_flags {
@@ -1761,6 +1761,32 @@ enum netdev_priv_flags {
IFF_NO_IP_ALIGN = BIT_ULL(34),
};
@@ -87,7 +87,7 @@ Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
#define IFF_802_1Q_VLAN IFF_802_1Q_VLAN
#define IFF_EBRIDGE IFF_EBRIDGE
#define IFF_BONDING IFF_BONDING
@@ -1901,6 +1927,8 @@ enum netdev_stat_type {
@@ -1881,6 +1907,8 @@ enum netdev_stat_type {
* @xdp_features: XDP capability supported by the device
* @priv_flags: Like 'flags' but invisible to userspace,
* see if.h for the definitions
@@ -96,7 +96,7 @@ Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
* @gflags: Global flags ( kept as legacy )
* @padded: How much padding added by alloc_netdev()
* @operstate: RFC2863 operstate
@@ -2146,6 +2174,7 @@ struct net_device {
@@ -2126,6 +2154,7 @@ struct net_device {
unsigned int flags;
xdp_features_t xdp_features;
unsigned long long priv_flags;
@@ -104,7 +104,7 @@ Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
const struct net_device_ops *netdev_ops;
const struct xdp_metadata_ops *xdp_metadata_ops;
int ifindex;
@@ -4306,7 +4335,6 @@ static inline bool netif_dormant(const s
@@ -4286,7 +4315,6 @@ static inline bool netif_dormant(const s
return test_bit(__LINK_STATE_DORMANT, &dev->state);
}
@@ -112,7 +112,7 @@ Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
/**
* netif_testing_on - mark device as under test.
* @dev: network device
@@ -5258,6 +5286,11 @@ static inline bool netif_is_failover_sla
@@ -5238,6 +5266,11 @@ static inline bool netif_is_failover_sla
return dev->priv_flags & IFF_FAILOVER_SLAVE;
}

View File

@@ -0,0 +1,104 @@
From 7d3846d95a5b5fa800031411d53078f2d775d2e6 Mon Sep 17 00:00:00 2001
From: Murat Sezgin <msezgin@codeaurora.org>
Date: Fri, 16 Jan 2015 16:54:08 -0800
Subject: [PATCH 301/500] ppp: Add PPP channel specific methods for PPTP and
L2TP types.
These methods are required for handling these types of PPP protocols
in the acceleration subsystem.
Change-Id: I7967573ee440a96af3f842300e2f021465a0a62c
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
---
drivers/net/ppp/pptp.c | 27 +++++++++++++++++++++++++++
net/l2tp/l2tp_ppp.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -603,9 +603,36 @@ static int pptp_ppp_ioctl(struct ppp_cha
return err;
}
+/* pptp_hold_chan() */
+static void pptp_hold_chan(struct ppp_channel *chan)
+{
+ struct sock *sk = (struct sock *)chan->private;
+
+ sock_hold(sk);
+}
+
+/* pptp_release_chan() */
+static void pptp_release_chan(struct ppp_channel *chan)
+{
+ struct sock *sk = (struct sock *)chan->private;
+
+ sock_put(sk);
+}
+
+/* pptp_get_channel_protocol()
+ * Return the protocol type of the PPTP over PPP protocol
+ */
+static int pptp_get_channel_protocol(struct ppp_channel *chan)
+{
+ return PX_PROTO_PPTP;
+}
+
static const struct ppp_channel_ops pptp_chan_ops = {
.start_xmit = pptp_xmit,
.ioctl = pptp_ppp_ioctl,
+ .get_channel_protocol = pptp_get_channel_protocol,
+ .hold = pptp_hold_chan,
+ .release = pptp_release_chan,
};
static struct proto pptp_sk_proto __read_mostly = {
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -123,9 +123,15 @@ struct pppol2tp_session {
};
static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb);
+static int pppol2tp_get_channel_protocol(struct ppp_channel *);
+static void pppol2tp_hold_chan(struct ppp_channel *);
+static void pppol2tp_release_chan(struct ppp_channel *);
static const struct ppp_channel_ops pppol2tp_chan_ops = {
.start_xmit = pppol2tp_xmit,
+ .get_channel_protocol = pppol2tp_get_channel_protocol,
+ .hold = pppol2tp_hold_chan,
+ .release = pppol2tp_release_chan,
};
static const struct proto_ops pppol2tp_ops;
@@ -328,6 +334,30 @@ error:
return error;
}
+/* pppol2tp_hold_chan() */
+static void pppol2tp_hold_chan(struct ppp_channel *chan)
+{
+ struct sock *sk = (struct sock *)chan->private;
+
+ sock_hold(sk);
+}
+
+/* pppol2tp_release_chan() */
+static void pppol2tp_release_chan(struct ppp_channel *chan)
+{
+ struct sock *sk = (struct sock *)chan->private;
+
+ sock_put(sk);
+}
+
+/* pppol2tp_get_channel_protocol()
+ * Return the protocol type of the L2TP over PPP protocol
+ */
+static int pppol2tp_get_channel_protocol(struct ppp_channel *chan)
+{
+ return PX_PROTO_OL2TP;
+}
+
/* Transmit function called by generic PPP driver. Sends PPP frame
* over PPPoL2TP socket.
*

View File

@@ -0,0 +1,608 @@
From 16de3e75ec92f88a454725c2e33e22b501c1a873 Mon Sep 17 00:00:00 2001
From: Murat Sezgin <quic_msezgin@quicinc.com>
Date: Wed, 10 May 2023 13:16:09 -0700
Subject: [PATCH 183/500] ppp: PPPoE acceleration support.
pppoe: Add return value to pppoe addressing get function
If the addressing doesn't have a netdevice, this should be
handled as a failure, so that the caller considers that
the get function failed.
Change-Id: Ia9a6b0e0f036a3434519d9f2194763486ca04583
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
Added some new APIs to the PPP/PPPoE kernel modules
for using from the hardware acceleration connection managers.
Change-Id: I2c16c6d6ccba8ffa14aec077c8dad1681535ae0b
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
net: ppp: rx/tx error and dropped pkt stats support
ppp_update_stats functions accepts rx/tx errors and dropped
pkt stats args.
Change-Id: Iba2f6ea2114d8a4678254332fec0ef7bc35bed2c
Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org>
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
ppp: Update the last_recv and last_xmit times.
These need to be updated for accelerated connections, so that
on demand mode will recognize the active traffic.
Change-Id: I3c0ee4e8f4c3bc4c7ce221e6109bfd82046d11b4
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
ppp: Add channel connect/disconnect notifier.
When a channel is connected or disconnected to a PPP
unit, a notification will be sent to the kernel subsystems
which are registered to this notifier. Notifier sends
the event type (connect or disconnect) along with the
PPP netdevice pointer.
Change-Id: I0d592084744c86e1c114ac66da68b214ddff5b5a
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
---
drivers/net/ppp/ppp_generic.c | 220 ++++++++++++++++++++++++++++++++++
drivers/net/ppp/pppoe.c | 83 ++++++++++++-
include/linux/if_pppox.h | 16 ++-
include/linux/ppp_channel.h | 52 ++++++++
net/l2tp/l2tp_core.c | 24 ++++
net/l2tp/l2tp_core.h | 2 +
6 files changed, 391 insertions(+), 6 deletions(-)
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -255,6 +255,24 @@ struct ppp_net {
#define seq_before(a, b) ((s32)((a) - (b)) < 0)
#define seq_after(a, b) ((s32)((a) - (b)) > 0)
+/*
+ * Registration/Unregistration methods
+ * for PPP channel connect and disconnect event notifications.
+ */
+RAW_NOTIFIER_HEAD(ppp_channel_connection_notifier_list);
+
+void ppp_channel_connection_register_notify(struct notifier_block *nb)
+{
+ raw_notifier_chain_register(&ppp_channel_connection_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(ppp_channel_connection_register_notify);
+
+void ppp_channel_connection_unregister_notify(struct notifier_block *nb)
+{
+ raw_notifier_chain_unregister(&ppp_channel_connection_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(ppp_channel_connection_unregister_notify);
+
/* Prototypes. */
static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
struct file *file, unsigned int cmd, unsigned long arg);
@@ -3468,6 +3486,7 @@ ppp_connect_channel(struct channel *pch,
struct ppp_net *pn;
int ret = -ENXIO;
int hdrlen;
+ int notify = 0;
pn = ppp_pernet(pch->chan_net);
@@ -3500,6 +3519,8 @@ ppp_connect_channel(struct channel *pch,
++ppp->n_channels;
pch->ppp = ppp;
refcount_inc(&ppp->file.refcnt);
+ notify = 1;
+
ppp_unlock(ppp);
ret = 0;
@@ -3507,6 +3528,14 @@ ppp_connect_channel(struct channel *pch,
write_unlock_bh(&pch->upl);
out:
mutex_unlock(&pn->all_ppp_mutex);
+
+ if (notify && ppp && ppp->dev) {
+ dev_hold(ppp->dev);
+ raw_notifier_call_chain(&ppp_channel_connection_notifier_list,
+ PPP_CHANNEL_CONNECT, ppp->dev);
+ dev_put(ppp->dev);
+ }
+
return ret;
}
@@ -3524,6 +3553,13 @@ ppp_disconnect_channel(struct channel *p
pch->ppp = NULL;
write_unlock_bh(&pch->upl);
if (ppp) {
+ if (ppp->dev) {
+ dev_hold(ppp->dev);
+ raw_notifier_call_chain(&ppp_channel_connection_notifier_list,
+ PPP_CHANNEL_DISCONNECT, ppp->dev);
+ dev_put(ppp->dev);
+ }
+
/* remove it from the ppp unit's list */
ppp_lock(ppp);
list_del(&pch->clist);
@@ -3603,6 +3639,188 @@ static void *unit_find(struct idr *p, in
return idr_find(p, n);
}
+/* Updates the PPP interface statistics. */
+void ppp_update_stats(struct net_device *dev, unsigned long rx_packets,
+ unsigned long rx_bytes, unsigned long tx_packets,
+ unsigned long tx_bytes, unsigned long rx_errors,
+ unsigned long tx_errors, unsigned long rx_dropped,
+ unsigned long tx_dropped)
+{
+ struct ppp *ppp;
+
+ if (!dev)
+ return;
+
+ if (dev->type != ARPHRD_PPP)
+ return;
+
+ ppp = netdev_priv(dev);
+
+ ppp_xmit_lock(ppp);
+ ppp->stats64.tx_packets += tx_packets;
+ ppp->stats64.tx_bytes += tx_bytes;
+ ppp->dev->stats.tx_errors += tx_errors;
+ ppp->dev->stats.tx_dropped += tx_dropped;
+ if (tx_packets)
+ ppp->last_xmit = jiffies;
+ ppp_xmit_unlock(ppp);
+
+ ppp_recv_lock(ppp);
+ ppp->stats64.rx_packets += rx_packets;
+ ppp->stats64.rx_bytes += rx_bytes;
+ ppp->dev->stats.rx_errors += rx_errors;
+ ppp->dev->stats.rx_dropped += rx_dropped;
+ if (rx_packets)
+ ppp->last_recv = jiffies;
+ ppp_recv_unlock(ppp);
+}
+
+/* Returns >0 if the device is a multilink PPP netdevice, 0 if not or < 0 if
+ * the device is not PPP.
+ */
+int ppp_is_multilink(struct net_device *dev)
+{
+ struct ppp *ppp;
+ unsigned int flags;
+
+ if (!dev)
+ return -1;
+
+ if (dev->type != ARPHRD_PPP)
+ return -1;
+
+ ppp = netdev_priv(dev);
+ ppp_lock(ppp);
+ flags = ppp->flags;
+ ppp_unlock(ppp);
+
+ if (flags & SC_MULTILINK)
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL(ppp_is_multilink);
+
+/* ppp_channel_get_protocol()
+ * Call this to obtain the underlying protocol of the PPP channel,
+ * e.g. PX_PROTO_OE
+ *
+ * NOTE: Some channels do not use PX sockets so the protocol value may be very
+ * different for them.
+ * NOTE: -1 indicates failure.
+ * NOTE: Once you know the channel protocol you may then either cast 'chan' to
+ * its sub-class or use the channel protocol specific API's as provided by that
+ * channel sub type.
+ */
+int ppp_channel_get_protocol(struct ppp_channel *chan)
+{
+ if (!chan->ops->get_channel_protocol)
+ return -1;
+
+ return chan->ops->get_channel_protocol(chan);
+}
+EXPORT_SYMBOL(ppp_channel_get_protocol);
+
+/* ppp_channel_hold()
+ * Call this to hold a channel.
+ *
+ * Returns true on success or false if the hold could not happen.
+ *
+ * NOTE: chan must be protected against destruction during this call -
+ * either by correct locking etc. or because you already have an implicit
+ * or explicit hold to the channel already and this is an additional hold.
+ */
+bool ppp_channel_hold(struct ppp_channel *chan)
+{
+ if (!chan->ops->hold)
+ return false;
+
+ chan->ops->hold(chan);
+ return true;
+}
+EXPORT_SYMBOL(ppp_channel_hold);
+
+/* ppp_channel_release()
+ * Call this to release a hold you have upon a channel
+ */
+void ppp_channel_release(struct ppp_channel *chan)
+{
+ chan->ops->release(chan);
+}
+EXPORT_SYMBOL(ppp_channel_release);
+
+/* ppp_hold_channels()
+ * Returns the PPP channels of the PPP device, storing each one into
+ * channels[].
+ *
+ * channels[] has chan_sz elements.
+ * This function returns the number of channels stored, up to chan_sz.
+ * It will return < 0 if the device is not PPP.
+ *
+ * You MUST release the channels using ppp_release_channels().
+ */
+int ppp_hold_channels(struct net_device *dev, struct ppp_channel *channels[],
+ unsigned int chan_sz)
+{
+ struct ppp *ppp;
+ int c;
+ struct channel *pch;
+
+ if (!dev)
+ return -1;
+
+ if (dev->type != ARPHRD_PPP)
+ return -1;
+
+ ppp = netdev_priv(dev);
+
+ c = 0;
+ ppp_lock(ppp);
+ list_for_each_entry(pch, &ppp->channels, clist) {
+ struct ppp_channel *chan;
+
+ if (!pch->chan) {
+ /* Channel is going / gone away */
+ continue;
+ }
+
+ if (c == chan_sz) {
+ /* No space to record channel */
+ ppp_unlock(ppp);
+ return c;
+ }
+
+ /* Hold the channel, if supported */
+ chan = pch->chan;
+ if (!chan->ops->hold)
+ continue;
+
+ chan->ops->hold(chan);
+
+ /* Record the channel */
+ channels[c++] = chan;
+ }
+ ppp_unlock(ppp);
+ return c;
+}
+EXPORT_SYMBOL(ppp_hold_channels);
+
+/* ppp_release_channels()
+ * Releases channels
+ */
+void ppp_release_channels(struct ppp_channel *channels[], unsigned int chan_sz)
+{
+ unsigned int c;
+
+ for (c = 0; c < chan_sz; ++c) {
+ struct ppp_channel *chan;
+
+ chan = channels[c];
+ chan->ops->release(chan);
+ }
+}
+EXPORT_SYMBOL(ppp_release_channels);
+
/* Module/initialization stuff */
module_init(ppp_init);
@@ -3619,6 +3837,8 @@ EXPORT_SYMBOL(ppp_input_error);
EXPORT_SYMBOL(ppp_output_wakeup);
EXPORT_SYMBOL(ppp_register_compressor);
EXPORT_SYMBOL(ppp_unregister_compressor);
+EXPORT_SYMBOL(ppp_update_stats);
+
MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV(PPP_MAJOR, 0);
MODULE_ALIAS_RTNL_LINK("ppp");
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -62,6 +62,7 @@
#include <linux/inetdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/if_arp.h>
#include <linux/init.h>
#include <linux/if_ether.h>
#include <linux/if_pppox.h>
@@ -87,7 +88,7 @@
static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
static const struct proto_ops pppoe_ops;
-static const struct ppp_channel_ops pppoe_chan_ops;
+static const struct pppoe_channel_ops pppoe_chan_ops;
/* per-net private data for this module */
static unsigned int pppoe_net_id __read_mostly;
@@ -645,6 +646,7 @@ static int pppoe_connect(struct socket *
if (stage_session(po->pppoe_pa.sid)) {
pppox_unbind_sock(sk);
pn = pppoe_pernet(sock_net(sk));
+
delete_item(pn, po->pppoe_pa.sid,
po->pppoe_pa.remote, po->pppoe_ifindex);
if (po->pppoe_dev) {
@@ -692,7 +694,7 @@ static int pppoe_connect(struct socket *
po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr) - 2;
po->chan.private = sk;
- po->chan.ops = &pppoe_chan_ops;
+ po->chan.ops = (struct ppp_channel_ops *)&pppoe_chan_ops;
error = ppp_register_net_channel(dev_net(dev), &po->chan);
if (error) {
@@ -995,9 +997,80 @@ static int pppoe_fill_forward_path(struc
return 0;
}
-static const struct ppp_channel_ops pppoe_chan_ops = {
- .start_xmit = pppoe_xmit,
- .fill_forward_path = pppoe_fill_forward_path,
+/************************************************************************
+ *
+ * function called by generic PPP driver to hold channel
+ *
+ ***********************************************************************/
+static void pppoe_hold_chan(struct ppp_channel *chan)
+{
+ struct sock *sk = (struct sock *)chan->private;
+
+ sock_hold(sk);
+}
+
+/************************************************************************
+ *
+ * function called by generic PPP driver to release channel
+ *
+ ***********************************************************************/
+static void pppoe_release_chan(struct ppp_channel *chan)
+{
+ struct sock *sk = (struct sock *)chan->private;
+
+ sock_put(sk);
+}
+
+/************************************************************************
+ *
+ * function called to get the channel protocol type
+ *
+ ***********************************************************************/
+static int pppoe_get_channel_protocol(struct ppp_channel *chan)
+{
+ return PX_PROTO_OE;
+}
+
+/************************************************************************
+ *
+ * function called to get the PPPoE channel addressing
+ * NOTE: This function returns a HOLD to the netdevice
+ *
+ ***********************************************************************/
+static int pppoe_get_addressing(struct ppp_channel *chan,
+ struct pppoe_opt *addressing)
+{
+ struct sock *sk = (struct sock *)chan->private;
+ struct pppox_sock *po = pppox_sk(sk);
+ int err = 0;
+
+ *addressing = po->proto.pppoe;
+ if (!addressing->dev)
+ return -ENODEV;
+
+ dev_hold(addressing->dev);
+ return err;
+}
+
+/* pppoe_channel_addressing_get()
+ * Return PPPoE channel specific addressing information.
+ */
+int pppoe_channel_addressing_get(struct ppp_channel *chan,
+ struct pppoe_opt *addressing)
+{
+ return pppoe_get_addressing(chan, addressing);
+}
+EXPORT_SYMBOL(pppoe_channel_addressing_get);
+
+static const struct pppoe_channel_ops pppoe_chan_ops = {
+ /* PPPoE specific channel ops */
+ .get_addressing = pppoe_get_addressing,
+ /* General ppp channel ops */
+ .ops.start_xmit = pppoe_xmit,
+ .ops.fill_forward_path = pppoe_fill_forward_path,
+ .ops.get_channel_protocol = pppoe_get_channel_protocol,
+ .ops.hold = pppoe_hold_chan,
+ .ops.release = pppoe_release_chan,
};
static int pppoe_recvmsg(struct socket *sock, struct msghdr *m,
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -1,11 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Linux PPP over X - Generic PPP transport layer sockets
- * Linux PPP over Ethernet (PPPoE) Socket Implementation (RFC 2516)
+ * Linux PPP over Ethernet (PPPoE) Socket Implementation (RFC 2516)
*
* This file supplies definitions required by the PPP over Ethernet driver
* (pppox.c). All version information wrt this file is located in pppox.c
*/
+
#ifndef __LINUX_IF_PPPOX_H
#define __LINUX_IF_PPPOX_H
@@ -91,4 +92,17 @@ enum {
PPPOX_DEAD = 16 /* dead, useless, please clean me up!*/
};
+/*
+ * PPPoE Channel specific operations
+ */
+struct pppoe_channel_ops {
+ /* Must be first - general to all PPP channels */
+ struct ppp_channel_ops ops;
+ int (*get_addressing)(struct ppp_channel *, struct pppoe_opt *);
+};
+
+/* Return PPPoE channel specific addressing information */
+extern int pppoe_channel_addressing_get(struct ppp_channel *chan,
+ struct pppoe_opt *addressing);
+
#endif /* !(__LINUX_IF_PPPOX_H) */
--- a/include/linux/ppp_channel.h
+++ b/include/linux/ppp_channel.h
@@ -19,6 +19,11 @@
#include <linux/skbuff.h>
#include <linux/poll.h>
#include <net/net_namespace.h>
+#include <linux/notifier.h>
+
+/* PPP channel connection event types */
+#define PPP_CHANNEL_DISCONNECT 0
+#define PPP_CHANNEL_CONNECT 1
struct net_device_path;
struct net_device_path_ctx;
@@ -33,6 +38,15 @@ struct ppp_channel_ops {
int (*fill_forward_path)(struct net_device_path_ctx *,
struct net_device_path *,
const struct ppp_channel *);
+
+ /* Get channel protocol type, one of PX_PROTO_XYZ or specific to
+ * the channel subtype
+ */
+ int (*get_channel_protocol)(struct ppp_channel *);
+ /* Hold the channel from being destroyed */
+ void (*hold)(struct ppp_channel *);
+ /* Release hold on the channel */
+ void (*release)(struct ppp_channel *);
};
struct ppp_channel {
@@ -47,6 +61,38 @@ struct ppp_channel {
};
#ifdef __KERNEL__
+/* Call this to obtain the underlying protocol of the PPP channel,
+ * e.g. PX_PROTO_OE
+ */
+extern int ppp_channel_get_protocol(struct ppp_channel *);
+
+/* Call this to hold a channel */
+extern bool ppp_channel_hold(struct ppp_channel *);
+
+/* Call this to release a hold you have upon a channel */
+extern void ppp_channel_release(struct ppp_channel *);
+
+/* Release hold on PPP channels */
+extern void ppp_release_channels(struct ppp_channel *channels[],
+ unsigned int chan_sz);
+
+/* Hold PPP channels for the PPP device */
+extern int ppp_hold_channels(struct net_device *dev,
+ struct ppp_channel *channels[],
+ unsigned int chan_sz);
+
+/* Test if the ppp device is a multi-link ppp device */
+extern int ppp_is_multilink(struct net_device *dev);
+
+/* Update statistics of the PPP net_device by incrementing related
+ * statistics field value with corresponding parameter
+ */
+extern void ppp_update_stats(struct net_device *dev, unsigned long rx_packets,
+ unsigned long rx_bytes, unsigned long tx_packets,
+ unsigned long tx_bytes, unsigned long rx_errors,
+ unsigned long tx_errors, unsigned long rx_dropped,
+ unsigned long tx_dropped);
+
/* Called by the channel when it can send some more data. */
extern void ppp_output_wakeup(struct ppp_channel *);
@@ -76,6 +122,12 @@ extern int ppp_unit_number(struct ppp_ch
/* Get the device name associated with a channel, or NULL if none */
extern char *ppp_dev_name(struct ppp_channel *);
+/* Register the PPP channel connect notifier */
+extern void ppp_channel_connection_register_notify(struct notifier_block *nb);
+
+/* Unregister the PPP channel connect notifier */
+extern void ppp_channel_connection_unregister_notify(struct notifier_block *nb);
+
/*
* SMP locking notes:
* The channel code must ensure that when it calls ppp_unregister_channel,
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -403,6 +403,30 @@ err_tlock:
}
EXPORT_SYMBOL_GPL(l2tp_session_register);
+void l2tp_stats_update(struct l2tp_tunnel *tunnel,
+ struct l2tp_session *session,
+ struct l2tp_stats *stats)
+{
+ atomic_long_add(atomic_long_read(&stats->rx_packets),
+ &tunnel->stats.rx_packets);
+ atomic_long_add(atomic_long_read(&stats->rx_bytes),
+ &tunnel->stats.rx_bytes);
+ atomic_long_add(atomic_long_read(&stats->tx_packets),
+ &tunnel->stats.tx_packets);
+ atomic_long_add(atomic_long_read(&stats->tx_bytes),
+ &tunnel->stats.tx_bytes);
+
+ atomic_long_add(atomic_long_read(&stats->rx_packets),
+ &session->stats.rx_packets);
+ atomic_long_add(atomic_long_read(&stats->rx_bytes),
+ &session->stats.rx_bytes);
+ atomic_long_add(atomic_long_read(&stats->tx_packets),
+ &session->stats.tx_packets);
+ atomic_long_add(atomic_long_read(&stats->tx_bytes),
+ &session->stats.tx_bytes);
+}
+EXPORT_SYMBOL_GPL(l2tp_stats_update);
+
/*****************************************************************************
* Receive data handling
*****************************************************************************/
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -231,6 +231,8 @@ struct l2tp_session *l2tp_session_get(co
struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth);
struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net,
const char *ifname);
+void l2tp_stats_update(struct l2tp_tunnel *tunnel, struct l2tp_session *session,
+ struct l2tp_stats *stats);
/* Tunnel and session lifetime management.
* Creation of a new instance is a two-step process: create, then register.

View File

@@ -0,0 +1,139 @@
From bd2254aed96e33fc84c24d54894fe606f474360d Mon Sep 17 00:00:00 2001
From: Murat Sezgin <msezgin@codeaurora.org>
Date: Fri, 26 Feb 2016 15:26:07 -0800
Subject: [PATCH 302/500] inet: pptp: Added API to get PPTP session info for
NSS acceleration
The API are needed by NSS modules to query PPTP session information
using the PPTP channel or session ID. The information is needed for
accelerating PPTP flows by NSS
Change-Id: I27408e9bee58f186a4ab99fa360bbef26b02c81b
Signed-off-by: Shyam Sunder <ssunde@codeaurora.org>
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
---
drivers/net/ppp/pptp.c | 75 ++++++++++++++++++++++++++++++++++++++++
include/linux/if_pppox.h | 8 +++++
2 files changed, 83 insertions(+)
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -91,6 +91,31 @@ static int lookup_chan_dst(u16 call_id,
return i < MAX_CALLID;
}
+/* Search a pptp session based on peer call id and peer ip address */
+static int lookup_session_dst(struct pptp_opt *opt, u16 call_id, __be32 d_addr)
+{
+ struct pppox_sock *sock;
+ int i = 1;
+
+ rcu_read_lock();
+ for_each_set_bit_from(i, callid_bitmap, MAX_CALLID) {
+ sock = rcu_dereference(callid_sock[i]);
+ if (!sock)
+ continue;
+
+ if (sock->proto.pptp.dst_addr.call_id == call_id &&
+ sock->proto.pptp.dst_addr.sin_addr.s_addr == d_addr) {
+ sock_hold(sk_pppox(sock));
+ memcpy(opt, &sock->proto.pptp, sizeof(struct pptp_opt));
+ sock_put(sk_pppox(sock));
+ rcu_read_unlock();
+ return 0;
+ }
+ }
+ rcu_read_unlock();
+ return -EINVAL;
+}
+
static int add_chan(struct pppox_sock *sock,
struct pptp_addr *sa)
{
@@ -258,7 +283,12 @@ static int pptp_xmit(struct ppp_channel
ip_select_ident(net, skb, NULL);
ip_send_check(iph);
+ /* set incoming interface as the ppp interface */
+ if (skb->skb_iif)
+ skb->skb_iif = ppp_dev_index(chan);
+
ip_local_out(net, skb->sk, skb);
+
return 1;
tx_error:
@@ -371,6 +401,7 @@ static int pptp_rcv(struct sk_buff *skb)
if (po) {
skb_dst_drop(skb);
nf_reset_ct(skb);
+ skb->skb_iif = ppp_dev_index(&po->chan);
return sk_receive_skb(sk_pppox(po), skb, 0);
}
drop:
@@ -603,6 +634,50 @@ static int pptp_ppp_ioctl(struct ppp_cha
return err;
}
+/* pptp_channel_addressing_get()
+ * Return PPTP channel specific addressing information.
+ */
+void pptp_channel_addressing_get(struct pptp_opt *opt, struct ppp_channel *chan)
+{
+ struct sock *sk;
+ struct pppox_sock *po;
+
+ if (!opt)
+ return;
+
+ sk = (struct sock *)chan->private;
+ if (!sk)
+ return;
+
+ sock_hold(sk);
+
+ /* This is very unlikely, but check the socket is connected state */
+ if (unlikely(sock_flag(sk, SOCK_DEAD) ||
+ !(sk->sk_state & PPPOX_CONNECTED))) {
+ sock_put(sk);
+ return;
+ }
+
+ po = pppox_sk(sk);
+ memcpy(opt, &po->proto.pptp, sizeof(struct pptp_opt));
+ sock_put(sk);
+}
+EXPORT_SYMBOL(pptp_channel_addressing_get);
+
+/* pptp_session_find()
+ * Search and return a PPTP session info based on peer callid and IP
+ * address. The function accepts the parameters in network byte order.
+ */
+int pptp_session_find(struct pptp_opt *opt, __be16 peer_call_id,
+ __be32 peer_ip_addr)
+{
+ if (!opt)
+ return -EINVAL;
+
+ return lookup_session_dst(opt, ntohs(peer_call_id), peer_ip_addr);
+}
+EXPORT_SYMBOL(pptp_session_find);
+
/* pptp_hold_chan() */
static void pptp_hold_chan(struct ppp_channel *chan)
{
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -105,4 +105,12 @@ struct pppoe_channel_ops {
extern int pppoe_channel_addressing_get(struct ppp_channel *chan,
struct pppoe_opt *addressing);
+/* Lookup PPTP session info and return PPTP session */
+extern int pptp_session_find(struct pptp_opt *opt, __be16 peer_call_id,
+ __be32 peer_ip_addr);
+
+/* Return PPTP session information given the channel */
+extern void pptp_channel_addressing_get(struct pptp_opt *opt,
+ struct ppp_channel *chan);
+
#endif /* !(__LINUX_IF_PPPOX_H) */

View File

@@ -0,0 +1,36 @@
From fb2393132ddf7af47b6b5dd67b57048f4b914faa Mon Sep 17 00:00:00 2001
From: ratheesh kannoth <rkannoth@codeaurora.org>
Date: Mon, 13 Nov 2017 15:10:10 +0530
Subject: [PATCH 298/500] net :gre : Set skb->skb_iif number
skb->skb_iif should be set to GRE netdevice to accelerate
packet
Change-Id: I0af542d2fa64b87c51b9bf3803bb874299299026
Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org>
Signed-off-by: Subhash Kumar Katnpally <skatnapa@codeaurora.org>
Signed-off-by: Pavithra R <pavir@codeaurora.org>
---
net/ipv4/ip_gre.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -687,6 +687,8 @@ static netdev_tx_t ipgre_xmit(struct sk_
if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
goto free_skb;
+ skb->skb_iif = dev->ifindex;
+
__gre_xmit(skb, dev, tnl_params, skb->protocol);
return NETDEV_TX_OK;
@@ -770,6 +772,8 @@ static netdev_tx_t gre_tap_xmit(struct s
if (skb_cow_head(skb, dev->needed_headroom))
goto free_skb;
+ skb->skb_iif = dev->ifindex;
+
__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
return NETDEV_TX_OK;

View File

@@ -0,0 +1,56 @@
From cad2cc2ca7c6cb9b4428a0333c46713f82d2424d Mon Sep 17 00:00:00 2001
From: Ratheesh Kannoth <rkannoth@codeaurora.org>
Date: Fri, 6 Nov 2020 12:56:12 +0530
Subject: [PATCH 244/500] net: ppp: API to check compression enabled on PPP
device
Change-Id: I574c688a9299531263061534a51cc88fef5e069f
Signed-off-by: Ratheesh Kannoth <rkannoth@codeaurora.org>
Signed-off-by: Pavithra R <quic_pavir@quicinc.com>
---
drivers/net/ppp/ppp_generic.c | 22 ++++++++++++++++++++++
include/linux/ppp_channel.h | 2 ++
2 files changed, 24 insertions(+)
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -3675,6 +3675,28 @@ void ppp_update_stats(struct net_device
ppp_recv_unlock(ppp);
}
+/* Returns true if Compression is enabled on PPP device
+ */
+bool ppp_is_cp_enabled(struct net_device *dev)
+{
+ struct ppp *ppp;
+ bool flag = false;
+
+ if (!dev)
+ return false;
+
+ if (dev->type != ARPHRD_PPP)
+ return false;
+
+ ppp = netdev_priv(dev);
+ ppp_lock(ppp);
+ flag = !!ppp->xcomp || !!ppp->rcomp;
+ ppp_unlock(ppp);
+
+ return flag;
+}
+EXPORT_SYMBOL(ppp_is_cp_enabled);
+
/* Returns >0 if the device is a multilink PPP netdevice, 0 if not or < 0 if
* the device is not PPP.
*/
--- a/include/linux/ppp_channel.h
+++ b/include/linux/ppp_channel.h
@@ -81,6 +81,8 @@ extern int ppp_hold_channels(struct net_
struct ppp_channel *channels[],
unsigned int chan_sz);
+bool ppp_is_cp_enabled(struct net_device *dev);
+
/* Test if the ppp device is a multi-link ppp device */
extern int ppp_is_multilink(struct net_device *dev);

View File

@@ -0,0 +1,23 @@
From 74702bfe2627baa572303a4d4281bafa2cfa2464 Mon Sep 17 00:00:00 2001
From: Ratheesh Kannoth <rkannoth@codeaurora.org>
Date: Mon, 16 Nov 2020 17:34:25 +0530
Subject: [PATCH 264/500] net: ppp: Use flag to detect TX/RX compression
Change-Id: I3068377565fe172b2771b7878a6c933322f6c69e
Signed-off-by: Ratheesh Kannoth <rkannoth@codeaurora.org>
Signed-off-by: Pavithra R <quic_pavir@quicinc.com>
---
drivers/net/ppp/ppp_generic.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -3690,7 +3690,7 @@ bool ppp_is_cp_enabled(struct net_device
ppp = netdev_priv(dev);
ppp_lock(ppp);
- flag = !!ppp->xcomp || !!ppp->rcomp;
+ flag = !!(ppp->xstate & SC_COMP_RUN) || !!(ppp->rstate & SC_DECOMP_RUN);
ppp_unlock(ppp);
return flag;

View File

@@ -0,0 +1,84 @@
From a7f74f20856f3076d57cb2a986cfbe1d26cead41 Mon Sep 17 00:00:00 2001
From: ratheesh kannoth <rkannoth@codeaurora.org>
Date: Wed, 8 Jul 2015 11:13:57 +0530
Subject: [PATCH 306/500] net: l2tp: set skb->iif for pkt thru l2tp interface
Change-Id: I20eed270083ba9ac167d9672928483396e488133
Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org>
---
drivers/net/ppp/ppp_generic.c | 15 +++++++++++++++
include/linux/ppp_channel.h | 4 ++++
net/l2tp/l2tp_ppp.c | 4 ++++
3 files changed, 23 insertions(+)
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -2986,6 +2986,20 @@ char *ppp_dev_name(struct ppp_channel *c
return name;
}
+/* Return the PPP net device index */
+int ppp_dev_index(struct ppp_channel *chan)
+{
+ struct channel *pch = chan->ppp;
+ int ifindex = 0;
+
+ if (pch) {
+ read_lock_bh(&pch->upl);
+ if (pch->ppp && pch->ppp->dev)
+ ifindex = pch->ppp->dev->ifindex;
+ read_unlock_bh(&pch->upl);
+ }
+ return ifindex;
+}
/*
* Disconnect a channel from the generic layer.
@@ -3854,6 +3868,7 @@ EXPORT_SYMBOL(ppp_unregister_channel);
EXPORT_SYMBOL(ppp_channel_index);
EXPORT_SYMBOL(ppp_unit_number);
EXPORT_SYMBOL(ppp_dev_name);
+EXPORT_SYMBOL(ppp_dev_index);
EXPORT_SYMBOL(ppp_input);
EXPORT_SYMBOL(ppp_input_error);
EXPORT_SYMBOL(ppp_output_wakeup);
--- a/include/linux/ppp_channel.h
+++ b/include/linux/ppp_channel.h
@@ -19,6 +19,7 @@
#include <linux/skbuff.h>
#include <linux/poll.h>
#include <net/net_namespace.h>
+#include <linux/ppp_defs.h>
#include <linux/notifier.h>
/* PPP channel connection event types */
@@ -118,6 +119,9 @@ extern void ppp_unregister_channel(struc
/* Get the channel number for a channel */
extern int ppp_channel_index(struct ppp_channel *);
+/* Get the device index associated with a channel, or 0, if none */
+extern int ppp_dev_index(struct ppp_channel *);
+
/* Get the unit number associated with a channel, or -1 if none */
extern int ppp_unit_number(struct ppp_channel *);
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -243,6 +243,7 @@ static void pppol2tp_recv(struct l2tp_se
struct pppox_sock *po;
po = pppox_sk(sk);
+ skb->skb_iif = ppp_dev_index(&po->chan);
ppp_input(&po->chan, skb);
} else {
if (sock_queue_rcv_skb(sk, skb) < 0) {
@@ -402,6 +403,9 @@ static int pppol2tp_xmit(struct ppp_chan
__skb_push(skb, 2);
skb->data[0] = PPP_ALLSTATIONS;
skb->data[1] = PPP_UI;
+ /* set incoming interface as the ppp interface */
+ if (skb->skb_iif)
+ skb->skb_iif = ppp_dev_index(chan);
local_bh_disable();
l2tp_xmit_skb(session, skb);

View File

@@ -0,0 +1,239 @@
From 974e8f230c2294f54d5151fe0dbbc68a3aecb347 Mon Sep 17 00:00:00 2001
From: Murat Sezgin <msezgin@codeaurora.org>
Date: Fri, 26 Feb 2016 15:18:08 -0800
Subject: [PATCH 307/500] net :l2tp: l2tp chan ops support get_addressing
l2tp channel ops support get_addressing() function. This
function can get l2tp tunnel/session/ip/port info.
Change-Id: Ica87438505c20376478092b95faaa3ecb8251596
Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org>
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
---
drivers/net/ppp/ppp_generic.c | 79 +++++++++++++++++++++++++++++++++++
include/linux/if_pppol2tp.h | 23 ++++++++++
include/linux/ppp_channel.h | 7 ++++
net/l2tp/l2tp_ppp.c | 53 +++++++++++++++++++----
4 files changed, 155 insertions(+), 7 deletions(-)
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -3737,6 +3737,32 @@ int ppp_is_multilink(struct net_device *
}
EXPORT_SYMBOL(ppp_is_multilink);
+/* __ppp_is_multilink()
+ * Returns >0 if the device is a multilink PPP netdevice, 0 if not or < 0
+ * if the device is not PPP. Caller should acquire ppp_lock before calling
+ * this function
+ */
+int __ppp_is_multilink(struct net_device *dev)
+{
+ struct ppp *ppp;
+ unsigned int flags;
+
+ if (!dev)
+ return -1;
+
+ if (dev->type != ARPHRD_PPP)
+ return -1;
+
+ ppp = netdev_priv(dev);
+ flags = ppp->flags;
+
+ if (flags & SC_MULTILINK)
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL(__ppp_is_multilink);
+
/* ppp_channel_get_protocol()
* Call this to obtain the underlying protocol of the PPP channel,
* e.g. PX_PROTO_OE
@@ -3841,6 +3867,59 @@ int ppp_hold_channels(struct net_device
}
EXPORT_SYMBOL(ppp_hold_channels);
+/* __ppp_hold_channels()
+ * Returns the PPP channels of the PPP device, storing each one
+ * into channels[].
+ *
+ * channels[] has chan_sz elements.
+ * This function returns the number of channels stored, up to chan_sz.
+ * It will return < 0 if the device is not PPP.
+ *
+ * You MUST acquire ppp_lock and release the channels using
+ * ppp_release_channels().
+ */
+int __ppp_hold_channels(struct net_device *dev, struct ppp_channel *channels[],
+ unsigned int chan_sz)
+{
+ struct ppp *ppp;
+ int c;
+ struct channel *pch;
+
+ if (!dev)
+ return -1;
+
+ if (dev->type != ARPHRD_PPP)
+ return -1;
+
+ ppp = netdev_priv(dev);
+
+ c = 0;
+ list_for_each_entry(pch, &ppp->channels, clist) {
+ struct ppp_channel *chan;
+
+ if (!pch->chan) {
+ /* Channel is going / gone away*/
+ continue;
+ }
+ if (c == chan_sz) {
+ /* No space to record channel */
+ return c;
+ }
+
+ /* Hold the channel, if supported */
+ chan = pch->chan;
+ if (!chan->ops->hold)
+ continue;
+
+ chan->ops->hold(chan);
+
+ /* Record the channel */
+ channels[c++] = chan;
+ }
+ return c;
+}
+EXPORT_SYMBOL(__ppp_hold_channels);
+
/* ppp_release_channels()
* Releases channels
*/
--- a/include/linux/if_pppol2tp.h
+++ b/include/linux/if_pppol2tp.h
@@ -12,4 +12,27 @@
#include <linux/in6.h>
#include <uapi/linux/if_pppol2tp.h>
+/*
+ * Holds L2TP channel info
+ */
+struct pppol2tp_common_addr {
+ int tunnel_version; /* v2 or v3 */
+ __u32 local_tunnel_id, remote_tunnel_id; /* tunnel id */
+ __u32 local_session_id, remote_session_id; /* session id */
+ struct sockaddr_in local_addr, remote_addr; /* ip address and port */
+};
+
+/*
+ * L2TP channel operations
+ */
+struct pppol2tp_channel_ops {
+ struct ppp_channel_ops ops; /* ppp channel ops */
+};
+
+/*
+ * exported function which calls pppol2tp channel's get addressing
+ * function
+ */
+extern int pppol2tp_channel_addressing_get(struct ppp_channel *,
+ struct pppol2tp_common_addr *);
#endif
--- a/include/linux/ppp_channel.h
+++ b/include/linux/ppp_channel.h
@@ -83,10 +83,17 @@ extern int ppp_hold_channels(struct net_
unsigned int chan_sz);
bool ppp_is_cp_enabled(struct net_device *dev);
+/* Hold PPP channels for the PPP device */
+extern int __ppp_hold_channels(struct net_device *dev,
+ struct ppp_channel *channels[],
+ unsigned int chan_sz);
/* Test if the ppp device is a multi-link ppp device */
extern int ppp_is_multilink(struct net_device *dev);
+/* Test if the ppp device is a multi-link ppp device */
+extern int __ppp_is_multilink(struct net_device *dev);
+
/* Update statistics of the PPP net_device by incrementing related
* statistics field value with corresponding parameter
*/
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -126,12 +126,11 @@ static int pppol2tp_xmit(struct ppp_chan
static int pppol2tp_get_channel_protocol(struct ppp_channel *);
static void pppol2tp_hold_chan(struct ppp_channel *);
static void pppol2tp_release_chan(struct ppp_channel *);
-
-static const struct ppp_channel_ops pppol2tp_chan_ops = {
- .start_xmit = pppol2tp_xmit,
- .get_channel_protocol = pppol2tp_get_channel_protocol,
- .hold = pppol2tp_hold_chan,
- .release = pppol2tp_release_chan,
+static const struct pppol2tp_channel_ops pppol2tp_chan_ops = {
+ .ops.start_xmit = pppol2tp_xmit,
+ .ops.get_channel_protocol = pppol2tp_get_channel_protocol,
+ .ops.hold = pppol2tp_hold_chan,
+ .ops.release = pppol2tp_release_chan,
};
static const struct proto_ops pppol2tp_ops;
@@ -359,6 +358,46 @@ static int pppol2tp_get_channel_protocol
return PX_PROTO_OL2TP;
}
+/* pppol2tp_get_addressing() */
+static int pppol2tp_get_addressing(struct ppp_channel *chan,
+ struct pppol2tp_common_addr *addr)
+{
+ struct sock *sk = (struct sock *)chan->private;
+ struct l2tp_session *session;
+ struct l2tp_tunnel *tunnel;
+ struct inet_sock *isk = NULL;
+ int err = -ENXIO;
+
+ /* Get session and tunnel contexts from the socket */
+ session = pppol2tp_sock_to_session(sk);
+ if (!session)
+ return err;
+
+ tunnel = session->tunnel;
+ isk = inet_sk(tunnel->sock);
+
+ addr->local_tunnel_id = tunnel->tunnel_id;
+ addr->remote_tunnel_id = tunnel->peer_tunnel_id;
+ addr->local_session_id = session->session_id;
+ addr->remote_session_id = session->peer_session_id;
+
+ addr->local_addr.sin_port = isk->inet_sport;
+ addr->remote_addr.sin_port = isk->inet_dport;
+ addr->local_addr.sin_addr.s_addr = isk->inet_saddr;
+ addr->remote_addr.sin_addr.s_addr = isk->inet_daddr;
+
+ sock_put(sk);
+ return 0;
+}
+
+/* pppol2tp_channel_addressing_get() */
+int pppol2tp_channel_addressing_get(struct ppp_channel *chan,
+ struct pppol2tp_common_addr *addr)
+{
+ return pppol2tp_get_addressing(chan, addr);
+}
+EXPORT_SYMBOL(pppol2tp_channel_addressing_get);
+
/* Transmit function called by generic PPP driver. Sends PPP frame
* over PPPoL2TP socket.
*
@@ -852,7 +891,7 @@ static int pppol2tp_connect(struct socke
po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
po->chan.private = sk;
- po->chan.ops = &pppol2tp_chan_ops;
+ po->chan.ops = &pppol2tp_chan_ops.ops;
po->chan.mtu = pppol2tp_tunnel_mtu(tunnel);
error = ppp_register_net_channel(sock_net(sk), &po->chan);

View File

@@ -0,0 +1,241 @@
From 98f71e72955490c9a1dcdb0f290e4a874a92ae4e Mon Sep 17 00:00:00 2001
From: pavir <pavir@codeaurora.org>
Date: Mon, 26 Dec 2016 14:41:20 +0530
Subject: [PATCH 308/500] net: l2tp: ppp_channel_proto_version API
New API added to retrieve channel version info
Change-Id: Ia4fd236c7cf6170a5034609e75de8c6e4ef79f7b
Signed-off-by: Shyam Sunder <ssunde@codeaurora.org>
Signed-off-by: pavir <pavir@codeaurora.org>
ppp: Fix ppp_connect_channel function's return value
The function should return 0 after all the successful
checks. The patch fixes failed PPPoE connections.
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
Change-Id: I6c4755b0b158ca9bd75403e01cb3c0dda193e9e0
Signed-off-by: Amruth S <quic_amrus@quicinc.com>
---
drivers/net/ppp/ppp_generic.c | 61 +++++++++++++++++++++++++++++++++++
include/linux/netdevice.h | 1 -
include/linux/ppp_channel.h | 9 ++++++
net/l2tp/l2tp_ppp.c | 40 ++++++++++++++++++++++-
4 files changed, 109 insertions(+), 2 deletions(-)
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -48,6 +48,7 @@
#include <net/slhc_vj.h>
#include <linux/atomic.h>
#include <linux/refcount.h>
+#include <linux/if_pppox.h>
#include <linux/nsproxy.h>
#include <net/net_namespace.h>
@@ -3500,6 +3501,8 @@ ppp_connect_channel(struct channel *pch,
struct ppp_net *pn;
int ret = -ENXIO;
int hdrlen;
+ int ppp_proto;
+ int version;
int notify = 0;
pn = ppp_pernet(pch->chan_net);
@@ -3533,6 +3536,30 @@ ppp_connect_channel(struct channel *pch,
++ppp->n_channels;
pch->ppp = ppp;
refcount_inc(&ppp->file.refcnt);
+
+ ppp_proto = ppp_channel_get_protocol(pch->chan);
+ switch (ppp_proto) {
+ case PX_PROTO_OL2TP:
+ version = ppp_channel_get_proto_version(pch->chan);
+ switch (version) {
+ case 2:
+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_L2TPV2;
+ break;
+ case 3:
+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_L2TPV3;
+ break;
+ }
+
+ break;
+
+ case PX_PROTO_PPTP:
+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_PPTP;
+ break;
+
+ default:
+ break;
+ }
+
notify = 1;
ppp_unlock(ppp);
@@ -3783,6 +3810,18 @@ int ppp_channel_get_protocol(struct ppp_
}
EXPORT_SYMBOL(ppp_channel_get_protocol);
+/* ppp_channel_get_proto_version()
+ * Call this to get channel protocol version
+ */
+int ppp_channel_get_proto_version(struct ppp_channel *chan)
+{
+ if (!chan->ops->get_channel_protocol_ver)
+ return -1;
+
+ return chan->ops->get_channel_protocol_ver(chan);
+}
+EXPORT_SYMBOL(ppp_channel_get_proto_version);
+
/* ppp_channel_hold()
* Call this to hold a channel.
*
@@ -3936,6 +3975,28 @@ void ppp_release_channels(struct ppp_cha
}
EXPORT_SYMBOL(ppp_release_channels);
+/* Check if ppp xmit lock is on hold */
+bool ppp_is_xmit_locked(struct net_device *dev)
+{
+ struct ppp *ppp;
+
+ if (!dev)
+ return false;
+
+ if (dev->type != ARPHRD_PPP)
+ return false;
+
+ ppp = netdev_priv(dev);
+ if (!ppp)
+ return false;
+
+ if (spin_is_locked(&(ppp)->wlock))
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL(ppp_is_xmit_locked);
+
/* Module/initialization stuff */
module_init(ppp_init);
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2259,7 +2259,6 @@ struct net_device {
unsigned char nested_level;
#endif
-
/* Protocol-specific pointers */
struct in_device __rcu *ip_ptr;
--- a/include/linux/ppp_channel.h
+++ b/include/linux/ppp_channel.h
@@ -44,6 +44,8 @@ struct ppp_channel_ops {
* the channel subtype
*/
int (*get_channel_protocol)(struct ppp_channel *);
+ /* Get channel protocol version */
+ int (*get_channel_protocol_ver)(struct ppp_channel *);
/* Hold the channel from being destroyed */
void (*hold)(struct ppp_channel *);
/* Release hold on the channel */
@@ -67,6 +69,9 @@ struct ppp_channel {
*/
extern int ppp_channel_get_protocol(struct ppp_channel *);
+/* Call this get protocol version */
+extern int ppp_channel_get_proto_version(struct ppp_channel *);
+
/* Call this to hold a channel */
extern bool ppp_channel_hold(struct ppp_channel *);
@@ -83,6 +88,10 @@ extern int ppp_hold_channels(struct net_
unsigned int chan_sz);
bool ppp_is_cp_enabled(struct net_device *dev);
+
+/* Test if ppp xmit lock is locked */
+extern bool ppp_is_xmit_locked(struct net_device *dev);
+
/* Hold PPP channels for the PPP device */
extern int __ppp_hold_channels(struct net_device *dev,
struct ppp_channel *channels[],
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -92,6 +92,7 @@
#include <net/ip.h>
#include <net/udp.h>
#include <net/inet_common.h>
+#include <linux/if_pppox.h>
#include <asm/byteorder.h>
#include <linux/atomic.h>
@@ -124,11 +125,13 @@ struct pppol2tp_session {
static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb);
static int pppol2tp_get_channel_protocol(struct ppp_channel *);
+static int pppol2tp_get_channel_protocol_ver(struct ppp_channel *);
static void pppol2tp_hold_chan(struct ppp_channel *);
static void pppol2tp_release_chan(struct ppp_channel *);
static const struct pppol2tp_channel_ops pppol2tp_chan_ops = {
.ops.start_xmit = pppol2tp_xmit,
.ops.get_channel_protocol = pppol2tp_get_channel_protocol,
+ .ops.get_channel_protocol_ver = pppol2tp_get_channel_protocol_ver,
.ops.hold = pppol2tp_hold_chan,
.ops.release = pppol2tp_release_chan,
};
@@ -358,6 +361,40 @@ static int pppol2tp_get_channel_protocol
return PX_PROTO_OL2TP;
}
+/* pppol2tp_get_channel_protocol_ver()
+ * Return the protocol version of the L2TP over PPP protocol
+ */
+static int pppol2tp_get_channel_protocol_ver(struct ppp_channel *chan)
+{
+ struct sock *sk;
+ struct l2tp_session *session;
+ struct l2tp_tunnel *tunnel;
+ int version = 0;
+
+ if (!(chan && chan->private)) {
+ return -1;
+ }
+
+ sk = (struct sock *)chan->private;
+
+ /* Get session and tunnel contexts from the socket */
+ session = pppol2tp_sock_to_session(sk);
+ if (!session) {
+ return -1;
+ }
+
+ tunnel = session->tunnel;
+ if (!tunnel) {
+ sock_put(sk);
+ return -1;
+ }
+
+ version = tunnel->version;
+
+ sock_put(sk);
+ return version;
+}
+
/* pppol2tp_get_addressing() */
static int pppol2tp_get_addressing(struct ppp_channel *chan,
struct pppol2tp_common_addr *addr)
@@ -443,7 +480,8 @@ static int pppol2tp_xmit(struct ppp_chan
skb->data[0] = PPP_ALLSTATIONS;
skb->data[1] = PPP_UI;
/* set incoming interface as the ppp interface */
- if (skb->skb_iif)
+ if ((skb->protocol == htons(ETH_P_IP)) ||
+ (skb->protocol == htons(ETH_P_IPV6)))
skb->skb_iif = ppp_dev_index(chan);
local_bh_disable();

View File

@@ -0,0 +1,254 @@
From 8b2fc28f1a1280663d30466c788ae80774fa1f29 Mon Sep 17 00:00:00 2001
From: Murat Sezgin <msezgin@codeaurora.org>
Date: Fri, 24 Apr 2020 11:00:19 -0700
Subject: [PATCH 303/500] inet: pptp: Enable offload mode for PPTP GRE sequence
number handling
Changes in this patch will allow all PPTP Data and LCP packets
to go via packet acceleration hardware. The hardware will take
care of Seq/Ack numbers update.
Change-Id: Ia5cd7893d9fda180174f78c3468279678422794d
Signed-off-by: Shyam Sunder <ssunde@codeaurora.org>
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
---
drivers/net/ppp/pptp.c | 136 +++++++++++++++++++++++++++++++++++++--
include/linux/if_pppox.h | 21 ++++++
2 files changed, 153 insertions(+), 4 deletions(-)
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -50,6 +50,8 @@ static struct proto pptp_sk_proto __read
static const struct ppp_channel_ops pptp_chan_ops;
static const struct proto_ops pptp_ops;
+static pptp_gre_seq_offload_callback_t __rcu pptp_gre_offload_xmit_cb;
+
static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr)
{
struct pppox_sock *sock;
@@ -116,6 +118,28 @@ static int lookup_session_dst(struct ppt
return -EINVAL;
}
+/* If offload mode set then this function sends all packets to
+ * offload module instead of network stack
+ */
+static int pptp_client_skb_xmit(struct sk_buff *skb,
+ struct net_device *pptp_dev)
+{
+ pptp_gre_seq_offload_callback_t pptp_gre_offload_cb_f;
+ int ret;
+
+ rcu_read_lock();
+ pptp_gre_offload_cb_f = rcu_dereference(pptp_gre_offload_xmit_cb);
+
+ if (!pptp_gre_offload_cb_f) {
+ rcu_read_unlock();
+ return -1;
+ }
+
+ ret = pptp_gre_offload_cb_f(skb, pptp_dev);
+ rcu_read_unlock();
+ return ret;
+}
+
static int add_chan(struct pppox_sock *sock,
struct pptp_addr *sa)
{
@@ -188,8 +212,11 @@ static int pptp_xmit(struct ppp_channel
struct rtable *rt;
struct net_device *tdev;
+ struct net_device *pptp_dev;
struct iphdr *iph;
int max_headroom;
+ int pptp_ifindex;
+ int ret;
if (sk_pppox(po)->sk_state & PPPOX_DEAD)
goto tx_error;
@@ -283,14 +310,33 @@ static int pptp_xmit(struct ppp_channel
ip_select_ident(net, skb, NULL);
ip_send_check(iph);
+ pptp_ifindex = ppp_dev_index(chan);
+
/* set incoming interface as the ppp interface */
if (skb->skb_iif)
- skb->skb_iif = ppp_dev_index(chan);
+ skb->skb_iif = pptp_ifindex;
- ip_local_out(net, skb->sk, skb);
+ /* If the PPTP GRE seq number offload module is not enabled yet
+ * then sends all PPTP GRE packets through linux network stack
+ */
+ if (!opt->pptp_offload_mode) {
+ ip_local_out(net, skb->sk, skb);
+ return 1;
+ }
- return 1;
+ pptp_dev = dev_get_by_index(&init_net, pptp_ifindex);
+ if (!pptp_dev)
+ goto tx_error;
+ /* If PPTP offload module is enabled then forward all PPTP GRE
+ * packets to PPTP GRE offload module
+ */
+ ret = pptp_client_skb_xmit(skb, pptp_dev);
+ dev_put(pptp_dev);
+ if (ret < 0)
+ goto tx_error;
+
+ return 1;
tx_error:
kfree_skb(skb);
return 1;
@@ -344,6 +390,13 @@ static int pptp_rcv_core(struct sock *sk
goto drop;
payload = skb->data + headersize;
+
+ /* If offload is enabled, we expect the offload module
+ * to handle PPTP GRE sequence number checks
+ */
+ if (opt->pptp_offload_mode)
+ goto allow_packet;
+
/* check for expected sequence number */
if (seq < opt->seq_recv + 1 || WRAPPED(opt->seq_recv, seq)) {
if ((payload[0] == PPP_ALLSTATIONS) && (payload[1] == PPP_UI) &&
@@ -504,7 +557,7 @@ static int pptp_connect(struct socket *s
opt->dst_addr = sp->sa_addr.pptp;
sk->sk_state |= PPPOX_CONNECTED;
-
+ opt->pptp_offload_mode = false;
end:
release_sock(sk);
return error;
@@ -678,6 +731,81 @@ int pptp_session_find(struct pptp_opt *o
}
EXPORT_SYMBOL(pptp_session_find);
+ /* Function to change the offload mode true/false for a PPTP session */
+static int pptp_set_offload_mode(bool accel_mode,
+ __be16 peer_call_id, __be32 peer_ip_addr)
+{
+ struct pppox_sock *sock;
+ int i = 1;
+
+ rcu_read_lock();
+ for_each_set_bit_from(i, callid_bitmap, MAX_CALLID) {
+ sock = rcu_dereference(callid_sock[i]);
+ if (!sock)
+ continue;
+
+ if (sock->proto.pptp.dst_addr.call_id == peer_call_id &&
+ sock->proto.pptp.dst_addr.sin_addr.s_addr == peer_ip_addr) {
+ sock_hold(sk_pppox(sock));
+ sock->proto.pptp.pptp_offload_mode = accel_mode;
+ sock_put(sk_pppox(sock));
+ rcu_read_unlock();
+ return 0;
+ }
+ }
+ rcu_read_unlock();
+ return -EINVAL;
+}
+
+/* Enable the PPTP session offload flag */
+int pptp_session_enable_offload_mode(__be16 peer_call_id, __be32 peer_ip_addr)
+{
+ return pptp_set_offload_mode(true, peer_call_id, peer_ip_addr);
+}
+EXPORT_SYMBOL(pptp_session_enable_offload_mode);
+
+/* Disable the PPTP session offload flag */
+int pptp_session_disable_offload_mode(__be16 peer_call_id, __be32 peer_ip_addr)
+{
+ return pptp_set_offload_mode(false, peer_call_id, peer_ip_addr);
+}
+EXPORT_SYMBOL(pptp_session_disable_offload_mode);
+
+/* Register the offload callback function on behalf of the module which
+ * will own the sequence and acknowledgment number updates for all
+ * PPTP GRE packets. All PPTP GRE packets are then transmitted to this
+ * module after encapsulation in order to ensure the correct seq/ack
+ * fields are set in the packets before transmission. This is required
+ * when PPTP flows are offloaded to acceleration engines, in-order to
+ * ensure consistency in sequence and ack numbers between PPTP control
+ * (PPP LCP) and data packets
+ */
+int pptp_register_gre_seq_offload_callback(pptp_gre_seq_offload_callback_t
+ pptp_gre_offload_cb)
+{
+ pptp_gre_seq_offload_callback_t pptp_gre_offload_cb_f;
+
+ rcu_read_lock();
+ pptp_gre_offload_cb_f = rcu_dereference(pptp_gre_offload_xmit_cb);
+
+ if (pptp_gre_offload_cb_f) {
+ rcu_read_unlock();
+ return -1;
+ }
+
+ rcu_assign_pointer(pptp_gre_offload_xmit_cb, pptp_gre_offload_cb);
+ rcu_read_unlock();
+ return 0;
+}
+EXPORT_SYMBOL(pptp_register_gre_seq_offload_callback);
+
+/* Unregister the PPTP GRE packets sequence number offload callback */
+void pptp_unregister_gre_seq_offload_callback(void)
+{
+ rcu_assign_pointer(pptp_gre_offload_xmit_cb, NULL);
+}
+EXPORT_SYMBOL(pptp_unregister_gre_seq_offload_callback);
+
/* pptp_hold_chan() */
static void pptp_hold_chan(struct ppp_channel *chan)
{
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -37,6 +37,7 @@ struct pptp_opt {
u32 ack_sent, ack_recv;
u32 seq_sent, seq_recv;
int ppp_flags;
+ bool pptp_offload_mode;
};
#include <net/sock.h>
@@ -101,6 +102,10 @@ struct pppoe_channel_ops {
int (*get_addressing)(struct ppp_channel *, struct pppoe_opt *);
};
+/* PPTP client callback */
+typedef int (*pptp_gre_seq_offload_callback_t)(struct sk_buff *skb,
+ struct net_device *pptp_dev);
+
/* Return PPPoE channel specific addressing information */
extern int pppoe_channel_addressing_get(struct ppp_channel *chan,
struct pppoe_opt *addressing);
@@ -113,4 +118,20 @@ extern int pptp_session_find(struct pptp
extern void pptp_channel_addressing_get(struct pptp_opt *opt,
struct ppp_channel *chan);
+/* Enable the PPTP session offload flag */
+extern int pptp_session_enable_offload_mode(__be16 peer_call_id,
+ __be32 peer_ip_addr);
+
+/* Disable the PPTP session offload flag */
+extern int pptp_session_disable_offload_mode(__be16 peer_call_id,
+ __be32 peer_ip_addr);
+
+/* Register the PPTP GRE packets sequence number offload callback */
+extern int
+pptp_register_gre_seq_offload_callback(pptp_gre_seq_offload_callback_t
+ pptp_client_cb);
+
+/* Unregister the PPTP GRE packets sequence number offload callback */
+extern void pptp_unregister_gre_seq_offload_callback(void);
+
#endif /* !(__LINUX_IF_PPPOX_H) */