diff --git a/target/linux/ipq806x/patches-6.6/990-0011-netfilter-nf_conntrack_ecache-Fix-NSS-ECM-BRK-kernel-panic.patch b/target/linux/ipq806x/patches-6.6/990-0006-netfilter-nf_conntrack_ecache-Fix-NSS-ECM-BRK-kernel-panic.patch similarity index 100% rename from target/linux/ipq806x/patches-6.6/990-0011-netfilter-nf_conntrack_ecache-Fix-NSS-ECM-BRK-kernel-panic.patch rename to target/linux/ipq806x/patches-6.6/990-0006-netfilter-nf_conntrack_ecache-Fix-NSS-ECM-BRK-kernel-panic.patch diff --git a/target/linux/ipq806x/patches-6.6/990-0029-add-proto-GRE-support.patch b/target/linux/ipq806x/patches-6.6/990-0007-add-proto-GRE-support.patch similarity index 100% rename from target/linux/ipq806x/patches-6.6/990-0029-add-proto-GRE-support.patch rename to target/linux/ipq806x/patches-6.6/990-0007-add-proto-GRE-support.patch diff --git a/target/linux/ipq806x/patches-6.6/990-0034-Add-Multicast-acceleration-support.patch b/target/linux/ipq806x/patches-6.6/990-0008-Add-Multicast-acceleration-support.patch similarity index 100% rename from target/linux/ipq806x/patches-6.6/990-0034-Add-Multicast-acceleration-support.patch rename to target/linux/ipq806x/patches-6.6/990-0008-Add-Multicast-acceleration-support.patch diff --git a/target/linux/ipq806x/patches-6.6/990-0036-qca-nss-gmac-of-net-return.patch b/target/linux/ipq806x/patches-6.6/990-0010-qca-nss-gmac-of-net-return.patch similarity index 100% rename from target/linux/ipq806x/patches-6.6/990-0036-qca-nss-gmac-of-net-return.patch rename to target/linux/ipq806x/patches-6.6/990-0010-qca-nss-gmac-of-net-return.patch diff --git a/target/linux/ipq806x/patches-6.6/990-0037-fix-socinfo.patch b/target/linux/ipq806x/patches-6.6/990-0011-fix-socinfo.patch similarity index 100% rename from target/linux/ipq806x/patches-6.6/990-0037-fix-socinfo.patch rename to target/linux/ipq806x/patches-6.6/990-0011-fix-socinfo.patch diff --git a/target/linux/ipq806x/patches-6.6/990-0051-qca-nss-cfi-support.patch b/target/linux/ipq806x/patches-6.6/990-0012-qca-nss-cfi-support.patch similarity index 100% rename from target/linux/ipq806x/patches-6.6/990-0051-qca-nss-cfi-support.patch rename to target/linux/ipq806x/patches-6.6/990-0012-qca-nss-cfi-support.patch diff --git a/target/linux/ipq806x/patches-6.6/990-0055-qca-nss-drv-add-qdisc-support.patch b/target/linux/ipq806x/patches-6.6/990-0013-qca-nss-drv-add-qdisc-support.patch similarity index 99% rename from target/linux/ipq806x/patches-6.6/990-0055-qca-nss-drv-add-qdisc-support.patch rename to target/linux/ipq806x/patches-6.6/990-0013-qca-nss-drv-add-qdisc-support.patch index 2930bbed7f..e3aec40856 100644 --- a/target/linux/ipq806x/patches-6.6/990-0055-qca-nss-drv-add-qdisc-support.patch +++ b/target/linux/ipq806x/patches-6.6/990-0013-qca-nss-drv-add-qdisc-support.patch @@ -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); /** diff --git a/target/linux/ipq806x/patches-6.6/990-0035-add-PPP-acceleration-support.patch b/target/linux/ipq806x/patches-6.6/990-0035-add-PPP-acceleration-support.patch deleted file mode 100644 index 363e25d95f..0000000000 --- a/target/linux/ipq806x/patches-6.6/990-0035-add-PPP-acceleration-support.patch +++ /dev/null @@ -1,1375 +0,0 @@ ---- a/drivers/net/ppp/ppp_generic.c -+++ b/drivers/net/ppp/ppp_generic.c -@@ -1,5 +1,21 @@ - // SPDX-License-Identifier: GPL-2.0-or-later - /* -+ ************************************************************************** -+ * Copyright (c) 2016, The Linux Foundation. All rights reserved. -+ * Permission to use, copy, modify, and/or distribute this software for -+ * any purpose with or without fee is hereby granted, provided that the -+ * above copyright notice and this permission notice appear in all copies. -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ ************************************************************************** -+ */ -+ -+/* - * Generic PPP layer for Linux. - * - * Copyright 1999-2002 Paul Mackerras. -@@ -48,11 +64,17 @@ - #include - #include - #include -+#include - - #include - #include - #include - -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+#include -+#include -+#endif -+ - #define PPP_VERSION "2.4.2" - - /* -@@ -255,6 +277,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); -@@ -1592,10 +1632,10 @@ static void ppp_dev_priv_destructor(stru - ppp_destroy_interface(ppp); - } - --static int ppp_fill_forward_path(struct net_device_path_ctx *ctx, -- struct net_device_path *path) -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+static int ppp_flow_offload_check(struct flow_offload_hw_path *path) - { -- struct ppp *ppp = netdev_priv(ctx->dev); -+ struct ppp *ppp = netdev_priv(path->dev); - struct ppp_channel *chan; - struct channel *pch; - -@@ -1607,11 +1647,12 @@ static int ppp_fill_forward_path(struct - - pch = list_first_entry(&ppp->channels, struct channel, clist); - chan = pch->chan; -- if (!chan->ops->fill_forward_path) -+ if (!chan->ops->flow_offload_check) - return -EOPNOTSUPP; - -- return chan->ops->fill_forward_path(ctx, path, chan); -+ return chan->ops->flow_offload_check(chan, path); - } -+#endif /* CONFIG_NF_FLOW_TABLE */ - - static const struct net_device_ops ppp_netdev_ops = { - .ndo_init = ppp_dev_init, -@@ -1619,7 +1660,9 @@ static const struct net_device_ops ppp_n - .ndo_start_xmit = ppp_start_xmit, - .ndo_siocdevprivate = ppp_net_siocdevprivate, - .ndo_get_stats64 = ppp_get_stats64, -- .ndo_fill_forward_path = ppp_fill_forward_path, -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ .ndo_flow_offload_check = ppp_flow_offload_check, -+#endif - }; - - static struct device_type ppp_type = { -@@ -2968,6 +3011,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. -@@ -3468,6 +3525,9 @@ 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); - -@@ -3500,6 +3560,32 @@ 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); - ret = 0; - -@@ -3507,6 +3593,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 +3618,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 +3704,323 @@ 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 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->xstate & SC_COMP_RUN) || !!(ppp->rstate & SC_DECOMP_RUN); -+ 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. -+ */ -+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_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 -+ * -+ * 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_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. -+ * -+ * 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_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 -+ */ -+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); -+ -+/* 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); -@@ -3614,11 +4032,14 @@ 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); - 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 - #include - #include -+#include - #include - #include - #include -@@ -73,6 +74,12 @@ - #include - #include - -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+#include -+#include -+#endif -+ -+ - #include - #include - #include -@@ -87,7 +94,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; -@@ -692,7 +699,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) { -@@ -972,9 +979,9 @@ static int pppoe_xmit(struct ppp_channel - return __pppoe_xmit(sk, skb); - } - --static int pppoe_fill_forward_path(struct net_device_path_ctx *ctx, -- struct net_device_path *path, -- const struct ppp_channel *chan) -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+static int pppoe_flow_offload_check(struct ppp_channel *chan, -+ struct flow_offload_hw_path *path) - { - struct sock *sk = chan->private; - struct pppox_sock *po = pppox_sk(sk); -@@ -982,22 +989,97 @@ static int pppoe_fill_forward_path(struc - - if (sock_flag(sk, SOCK_DEAD) || - !(sk->sk_state & PPPOX_CONNECTED) || !dev) -- return -1; -+ return -ENODEV; - -- path->type = DEV_PATH_PPPOE; -- path->encap.proto = htons(ETH_P_PPP_SES); -- path->encap.id = be16_to_cpu(po->num); -- memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN); -- memcpy(ctx->daddr, po->pppoe_pa.remote, ETH_ALEN); -- path->dev = ctx->dev; -- ctx->dev = dev; -+ path->dev = po->pppoe_dev; -+ path->flags |= FLOW_OFFLOAD_PATH_PPPOE; -+ memcpy(path->eth_src, po->pppoe_dev->dev_addr, ETH_ALEN); -+ memcpy(path->eth_dest, po->pppoe_pa.remote, ETH_ALEN); -+ path->pppoe_sid = be16_to_cpu(po->num); -+ -+ if (path->dev->netdev_ops->ndo_flow_offload_check) -+ return path->dev->netdev_ops->ndo_flow_offload_check(path); - - return 0; - } -+#endif /* CONFIG_NF_FLOW_TABLE */ -+ -+/************************************************************************ -+ * -+ * 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; -+} - --static const struct ppp_channel_ops pppoe_chan_ops = { -- .start_xmit = pppoe_xmit, -- .fill_forward_path = pppoe_fill_forward_path, -+/* 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, -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ .ops.flow_offload_check = pppoe_flow_offload_check, -+#endif -+ .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/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; -@@ -91,6 +93,79 @@ static int lookup_chan_dst(u16 call_id, - return i < MAX_CALLID; - } - -+/* Search a pptp session based on local call id, local and remote ip address */ -+static int lookup_session_src(struct pptp_opt *opt, u16 call_id, __be32 daddr, __be32 saddr) -+{ -+ 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.src_addr.call_id == call_id && -+ sock->proto.pptp.dst_addr.sin_addr.s_addr == daddr && -+ sock->proto.pptp.src_addr.sin_addr.s_addr == saddr) { -+ 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; -+} -+ -+/* 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; -+} -+ -+/* 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) - { -@@ -163,8 +238,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; -@@ -258,9 +336,33 @@ static int pptp_xmit(struct ppp_channel - ip_select_ident(net, skb, NULL); - ip_send_check(iph); - -- ip_local_out(net, skb->sk, skb); -- return 1; -+ pptp_ifindex = ppp_dev_index(chan); -+ -+ /* set incoming interface as the ppp interface */ -+ if (skb->skb_iif) -+ skb->skb_iif = pptp_ifindex; -+ -+ /* 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; -+ } -+ -+ 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; -@@ -314,6 +416,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) && -@@ -371,6 +480,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: -@@ -473,7 +583,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; -@@ -603,9 +713,169 @@ 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_session_find_by_src_callid() -+ * Search and return a PPTP session info based on src callid and IP -+ * address. The function accepts the parameters in network byte order. -+ */ -+int pptp_session_find_by_src_callid(struct pptp_opt *opt, __be16 src_call_id, -+ __be32 daddr, __be32 saddr) -+{ -+ if (!opt) -+ return -EINVAL; -+ -+ return lookup_session_src(opt, ntohs(src_call_id), daddr, saddr); -+} -+EXPORT_SYMBOL(pptp_session_find_by_src_callid); -+ -+ /* 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) -+{ -+ 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/include/linux/if_pppol2tp.h -+++ b/include/linux/if_pppol2tp.h -@@ -12,4 +12,27 @@ - #include - #include - -+/* -+ * 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/if_pppox.h -+++ b/include/linux/if_pppox.h -@@ -36,6 +36,7 @@ struct pptp_opt { - u32 ack_sent, ack_recv; - u32 seq_sent, seq_recv; - int ppp_flags; -+ bool pptp_offload_mode; - }; - #include - -@@ -91,4 +92,49 @@ 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 *); -+}; -+ -+/* 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); -+ -+/* Lookup PPTP session info and return PPTP session using sip, dip and local call id */ -+extern int pptp_session_find_by_src_callid(struct pptp_opt *opt, __be16 src_call_id, -+ __be32 daddr, __be32 saddr); -+ -+/* Lookup PPTP session info and return PPTP session using dip and peer call id */ -+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); -+ -+/* 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) */ ---- a/include/linux/ppp_channel.h -+++ b/include/linux/ppp_channel.h -@@ -19,6 +19,12 @@ - #include - #include - #include -+#include -+#include -+ -+/* PPP channel connection event types */ -+#define PPP_CHANNEL_DISCONNECT 0 -+#define PPP_CHANNEL_CONNECT 1 - - struct net_device_path; - struct net_device_path_ctx; -@@ -30,9 +36,20 @@ struct ppp_channel_ops { - int (*start_xmit)(struct ppp_channel *, struct sk_buff *); - /* Handle an ioctl call that has come in via /dev/ppp. */ - int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long); -- int (*fill_forward_path)(struct net_device_path_ctx *, -- struct net_device_path *, -- const struct ppp_channel *); -+ -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ int (*flow_offload_check)(struct ppp_channel *, struct flow_offload_hw_path *); -+#endif -+ /* Get channel protocol type, one of PX_PROTO_XYZ or specific to -+ * 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 */ -+ void (*release)(struct ppp_channel *); - }; - - struct ppp_channel { -@@ -47,6 +64,54 @@ 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 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 *); -+ -+/* 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 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[], -+ 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); -+ -+/* 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 *); - -@@ -70,12 +135,21 @@ 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 *); - - /* 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/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -1073,6 +1073,20 @@ struct dev_ifalias { - struct devlink; - struct tlsdev_ops; - -+struct flow_offload; -+struct flow_offload_hw_path; -+ -+enum flow_offload_type { -+ FLOW_OFFLOAD_ADD = 0, -+ FLOW_OFFLOAD_DEL, -+}; -+ -+enum nss_flow_offload_type { -+ NF_FLOW_OFFLOAD_UNSPEC = 0, -+ NF_FLOW_OFFLOAD_ROUTE, -+}; -+ -+ - struct netdev_net_notifier { - struct list_head list; - struct notifier_block *nb; -@@ -1626,6 +1640,12 @@ struct net_device_ops { - int (*ndo_bridge_dellink)(struct net_device *dev, - struct nlmsghdr *nlh, - u16 flags); -+ int (*ndo_flow_offload_check)(struct flow_offload_hw_path *path); -+ int (*ndo_flow_offload)(enum nss_flow_offload_type type, -+ struct flow_offload *flow, -+ struct flow_offload_hw_path *src, -+ struct flow_offload_hw_path *dest); -+ - int (*ndo_change_carrier)(struct net_device *dev, - bool new_carrier); - int (*ndo_get_phys_port_id)(struct net_device *dev, ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -171,10 +171,14 @@ enum nf_flow_flags { - NF_FLOW_HW_ESTABLISHED, - }; - --enum flow_offload_type { -- NF_FLOW_OFFLOAD_UNSPEC = 0, -- NF_FLOW_OFFLOAD_ROUTE, --}; -+ -+#define FLOW_OFFLOAD_SNAT 0x1 -+#define FLOW_OFFLOAD_DNAT 0x2 -+#define FLOW_OFFLOAD_DYING 0x4 -+#define FLOW_OFFLOAD_TEARDOWN 0x8 -+#define FLOW_OFFLOAD_HW 0x10 -+#define FLOW_OFFLOAD_KEEP 0x20 -+ - - struct flow_offload { - struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; -@@ -185,6 +189,25 @@ struct flow_offload { - struct rcu_head rcu_head; - }; - -+ -+#define FLOW_OFFLOAD_PATH_ETHERNET BIT(0) -+#define FLOW_OFFLOAD_PATH_VLAN BIT(1) -+#define FLOW_OFFLOAD_PATH_PPPOE BIT(2) -+#define FLOW_OFFLOAD_PATH_DSA BIT(3) -+ -+struct flow_offload_hw_path { -+ struct net_device *dev; -+ u32 flags; -+ -+ u8 eth_src[ETH_ALEN]; -+ u8 eth_dest[ETH_ALEN]; -+ u16 vlan_proto; -+ u16 vlan_id; -+ u16 pppoe_sid; -+ u16 dsa_port; -+}; -+ -+ - #define NF_FLOW_TIMEOUT (30 * HZ) - #define nf_flowtable_time_stamp (u32)jiffies - ---- 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. diff --git a/target/linux/ipq806x/patches-6.6/990-0085-OpenWRT-644-bridge_optimize_netfilter_hooks.patch.patch b/target/linux/ipq806x/patches-6.6/990-0085-OpenWRT-644-bridge_optimize_netfilter_hooks.patch.patch index 6402845c37..e6e9b08408 100644 --- a/target/linux/ipq806x/patches-6.6/990-0085-OpenWRT-644-bridge_optimize_netfilter_hooks.patch.patch +++ b/target/linux/ipq806x/patches-6.6/990-0085-OpenWRT-644-bridge_optimize_netfilter_hooks.patch.patch @@ -105,7 +105,7 @@ Signed-off-by: Murat Sezgin 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 { } }; -@@ -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 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; diff --git a/target/linux/ipq806x/patches-6.6/990-0184-net-add-fast-xmit-api.patch b/target/linux/ipq806x/patches-6.6/990-0184-net-add-fast-xmit-api.patch index 4108985cb4..6d8de1ba50 100644 --- a/target/linux/ipq806x/patches-6.6/990-0184-net-add-fast-xmit-api.patch +++ b/target/linux/ipq806x/patches-6.6/990-0184-net-add-fast-xmit-api.patch @@ -15,7 +15,7 @@ Signed-off-by: Ken Zhu --- 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; } diff --git a/target/linux/ipq806x/patches-6.6/990-0197-net-ipv4-ipv6-Added-route-table-update-notify-chain.patch b/target/linux/ipq806x/patches-6.6/990-0197-net-ipv4-ipv6-Added-route-table-update-notify-chain.patch index b9d601549f..8696887758 100644 --- a/target/linux/ipq806x/patches-6.6/990-0197-net-ipv4-ipv6-Added-route-table-update-notify-chain.patch +++ b/target/linux/ipq806x/patches-6.6/990-0197-net-ipv4-ipv6-Added-route-table-update-notify-chain.patch @@ -37,7 +37,7 @@ Signed-off-by: Murat Sezgin 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); diff --git a/target/linux/ipq806x/patches-6.6/990-0203-net-Add-netdevice-notification-for-bridge-activity.patch b/target/linux/ipq806x/patches-6.6/990-0203-net-Add-netdevice-notification-for-bridge-activity.patch index 944214bbb7..191fe013bd 100644 --- a/target/linux/ipq806x/patches-6.6/990-0203-net-Add-netdevice-notification-for-bridge-activity.patch +++ b/target/linux/ipq806x/patches-6.6/990-0203-net-Add-netdevice-notification-for-bridge-activity.patch @@ -18,7 +18,7 @@ Signed-off-by: Murat Sezgin --- 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, diff --git a/target/linux/ipq806x/patches-6.6/990-0205-bridge-Add-flag-to-force-netfilter-hook-evaluation.patch b/target/linux/ipq806x/patches-6.6/990-0205-bridge-Add-flag-to-force-netfilter-hook-evaluation.patch index 9466d6a12c..e328be71c7 100644 --- a/target/linux/ipq806x/patches-6.6/990-0205-bridge-Add-flag-to-force-netfilter-hook-evaluation.patch +++ b/target/linux/ipq806x/patches-6.6/990-0205-bridge-Add-flag-to-force-netfilter-hook-evaluation.patch @@ -35,7 +35,7 @@ Signed-off-by: Murat Sezgin } 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 { } }; -@@ -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 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; diff --git a/target/linux/ipq806x/patches-6.6/990-0214-net-bridge-Disable-custom-and-ebtables-calls-by-defa.patch b/target/linux/ipq806x/patches-6.6/990-0214-net-bridge-Disable-custom-and-ebtables-calls-by-defa.patch index 18eda1de9d..a80efe4d7a 100644 --- a/target/linux/ipq806x/patches-6.6/990-0214-net-bridge-Disable-custom-and-ebtables-calls-by-defa.patch +++ b/target/linux/ipq806x/patches-6.6/990-0214-net-bridge-Disable-custom-and-ebtables-calls-by-defa.patch @@ -14,7 +14,7 @@ Signed-off-by: Murat Sezgin --- 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; diff --git a/target/linux/ipq806x/patches-6.6/990-0224-net-Add-extra-priv_flag-support-in-netdevice.patch b/target/linux/ipq806x/patches-6.6/990-0224-net-Add-extra-priv_flag-support-in-netdevice.patch index dd2de732f4..445663bc83 100644 --- a/target/linux/ipq806x/patches-6.6/990-0224-net-Add-extra-priv_flag-support-in-netdevice.patch +++ b/target/linux/ipq806x/patches-6.6/990-0224-net-Add-extra-priv_flag-support-in-netdevice.patch @@ -54,7 +54,7 @@ Signed-off-by: Murat Sezgin 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 #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 * @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 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 /** * 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; } diff --git a/target/linux/ipq806x/patches-6.6/990-0340-ppp-Add-PPP-channel-specific-methods-for-PPTP-and-L2.patch b/target/linux/ipq806x/patches-6.6/990-0340-ppp-Add-PPP-channel-specific-methods-for-PPTP-and-L2.patch new file mode 100644 index 0000000000..7ee5964ffd --- /dev/null +++ b/target/linux/ipq806x/patches-6.6/990-0340-ppp-Add-PPP-channel-specific-methods-for-PPTP-and-L2.patch @@ -0,0 +1,104 @@ +From 7d3846d95a5b5fa800031411d53078f2d775d2e6 Mon Sep 17 00:00:00 2001 +From: Murat Sezgin +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 +--- + 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. + * diff --git a/target/linux/ipq806x/patches-6.6/990-0341-ppp-PPPoE-acceleration-support.patch b/target/linux/ipq806x/patches-6.6/990-0341-ppp-PPPoE-acceleration-support.patch new file mode 100644 index 0000000000..063b2015c1 --- /dev/null +++ b/target/linux/ipq806x/patches-6.6/990-0341-ppp-PPPoE-acceleration-support.patch @@ -0,0 +1,608 @@ +From 16de3e75ec92f88a454725c2e33e22b501c1a873 Mon Sep 17 00:00:00 2001 +From: Murat Sezgin +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 + +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 + +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 +Signed-off-by: Murat Sezgin + +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 + +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 +Signed-off-by: Murat Sezgin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include ++ ++/* 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. diff --git a/target/linux/ipq806x/patches-6.6/990-0342-inet-pptp-Added-API-to-get-PPTP-session-info-for-NSS.patch b/target/linux/ipq806x/patches-6.6/990-0342-inet-pptp-Added-API-to-get-PPTP-session-info-for-NSS.patch new file mode 100644 index 0000000000..c1a1c07e7d --- /dev/null +++ b/target/linux/ipq806x/patches-6.6/990-0342-inet-pptp-Added-API-to-get-PPTP-session-info-for-NSS.patch @@ -0,0 +1,139 @@ +From bd2254aed96e33fc84c24d54894fe606f474360d Mon Sep 17 00:00:00 2001 +From: Murat Sezgin +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 +Signed-off-by: Murat Sezgin +--- + 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) */ diff --git a/target/linux/ipq806x/patches-6.6/990-0343-net-gre-Set-skb-skb_iif-number.patch b/target/linux/ipq806x/patches-6.6/990-0343-net-gre-Set-skb-skb_iif-number.patch new file mode 100644 index 0000000000..3be0f8efd2 --- /dev/null +++ b/target/linux/ipq806x/patches-6.6/990-0343-net-gre-Set-skb-skb_iif-number.patch @@ -0,0 +1,36 @@ +From fb2393132ddf7af47b6b5dd67b57048f4b914faa Mon Sep 17 00:00:00 2001 +From: ratheesh kannoth +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 +Signed-off-by: Subhash Kumar Katnpally +Signed-off-by: Pavithra R +--- + 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; + diff --git a/target/linux/ipq806x/patches-6.6/990-0344-net-ppp-API-to-check-compression-enabled-on-PPP-devi.patch b/target/linux/ipq806x/patches-6.6/990-0344-net-ppp-API-to-check-compression-enabled-on-PPP-devi.patch new file mode 100644 index 0000000000..f83f310ff5 --- /dev/null +++ b/target/linux/ipq806x/patches-6.6/990-0344-net-ppp-API-to-check-compression-enabled-on-PPP-devi.patch @@ -0,0 +1,56 @@ +From cad2cc2ca7c6cb9b4428a0333c46713f82d2424d Mon Sep 17 00:00:00 2001 +From: Ratheesh Kannoth +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 +Signed-off-by: Pavithra R +--- + 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); + diff --git a/target/linux/ipq806x/patches-6.6/990-0345-net-ppp-Use-flag-to-detect-TX-RX-compression.patch b/target/linux/ipq806x/patches-6.6/990-0345-net-ppp-Use-flag-to-detect-TX-RX-compression.patch new file mode 100644 index 0000000000..89533aebfc --- /dev/null +++ b/target/linux/ipq806x/patches-6.6/990-0345-net-ppp-Use-flag-to-detect-TX-RX-compression.patch @@ -0,0 +1,23 @@ +From 74702bfe2627baa572303a4d4281bafa2cfa2464 Mon Sep 17 00:00:00 2001 +From: Ratheesh Kannoth +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 +Signed-off-by: Pavithra R +--- + 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; diff --git a/target/linux/ipq806x/patches-6.6/990-0346-net-l2tp-set-skb-iif-for-pkt-thru-l2tp-interface.patch b/target/linux/ipq806x/patches-6.6/990-0346-net-l2tp-set-skb-iif-for-pkt-thru-l2tp-interface.patch new file mode 100644 index 0000000000..1d5f2e309e --- /dev/null +++ b/target/linux/ipq806x/patches-6.6/990-0346-net-l2tp-set-skb-iif-for-pkt-thru-l2tp-interface.patch @@ -0,0 +1,84 @@ +From a7f74f20856f3076d57cb2a986cfbe1d26cead41 Mon Sep 17 00:00:00 2001 +From: ratheesh kannoth +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 +--- + 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 + #include + #include ++#include + #include + + /* 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); diff --git a/target/linux/ipq806x/patches-6.6/990-0347-net-l2tp-l2tp-chan-ops-support-get_addressing.patch b/target/linux/ipq806x/patches-6.6/990-0347-net-l2tp-l2tp-chan-ops-support-get_addressing.patch new file mode 100644 index 0000000000..2831275934 --- /dev/null +++ b/target/linux/ipq806x/patches-6.6/990-0347-net-l2tp-l2tp-chan-ops-support-get_addressing.patch @@ -0,0 +1,239 @@ +From 974e8f230c2294f54d5151fe0dbbc68a3aecb347 Mon Sep 17 00:00:00 2001 +From: Murat Sezgin +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 +Signed-off-by: Murat Sezgin +--- + 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 + #include + ++/* ++ * 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); diff --git a/target/linux/ipq806x/patches-6.6/990-0348-net-l2tp-ppp_channel_proto_version-API.patch b/target/linux/ipq806x/patches-6.6/990-0348-net-l2tp-ppp_channel_proto_version-API.patch new file mode 100644 index 0000000000..16de0bea76 --- /dev/null +++ b/target/linux/ipq806x/patches-6.6/990-0348-net-l2tp-ppp_channel_proto_version-API.patch @@ -0,0 +1,241 @@ +From 98f71e72955490c9a1dcdb0f290e4a874a92ae4e Mon Sep 17 00:00:00 2001 +From: pavir +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 +Signed-off-by: pavir + +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 +Change-Id: I6c4755b0b158ca9bd75403e01cb3c0dda193e9e0 +Signed-off-by: Amruth S +--- + 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 + #include + #include ++#include + + #include + #include +@@ -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 + #include + #include ++#include + + #include + #include +@@ -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(); diff --git a/target/linux/ipq806x/patches-6.6/990-0349-inet-pptp-Enable-offload-mode-for-PPTP-GRE-sequence-.patch b/target/linux/ipq806x/patches-6.6/990-0349-inet-pptp-Enable-offload-mode-for-PPTP-GRE-sequence-.patch new file mode 100644 index 0000000000..6aedf5870f --- /dev/null +++ b/target/linux/ipq806x/patches-6.6/990-0349-inet-pptp-Enable-offload-mode-for-PPTP-GRE-sequence-.patch @@ -0,0 +1,254 @@ +From 8b2fc28f1a1280663d30466c788ae80774fa1f29 Mon Sep 17 00:00:00 2001 +From: Murat Sezgin +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 +Signed-off-by: Murat Sezgin +--- + 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 + +@@ -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) */