mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
ipq60xx: add nss ecm kernel support for 5.15
This commit is contained in:
parent
3da5d6fffd
commit
88c0fe5c1a
@ -0,0 +1,615 @@
|
|||||||
|
--- a/include/linux/if_bridge.h
|
||||||
|
+++ b/include/linux/if_bridge.h
|
||||||
|
@@ -69,6 +69,9 @@ void brioctl_set(int (*hook)(struct net
|
||||||
|
void __user *uarg));
|
||||||
|
int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
|
||||||
|
struct ifreq *ifr, void __user *uarg);
|
||||||
|
+extern void br_dev_update_stats(struct net_device *dev,
|
||||||
|
+ struct rtnl_link_stats64 *nlstats);
|
||||||
|
+extern bool br_is_hairpin_enabled(struct net_device *dev);
|
||||||
|
|
||||||
|
extern void br_dev_update_stats(struct net_device *dev,
|
||||||
|
struct rtnl_link_stats64 *nlstats);
|
||||||
|
@@ -195,4 +198,42 @@ static inline clock_t br_get_ageing_time
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+extern struct net_device *br_port_dev_get(struct net_device *dev,
|
||||||
|
+ unsigned char *addr,
|
||||||
|
+ struct sk_buff *skb,
|
||||||
|
+ unsigned int cookie);
|
||||||
|
+extern void br_refresh_fdb_entry(struct net_device *dev, const char *addr);
|
||||||
|
+extern void br_fdb_entry_refresh(struct net_device *dev, const char *addr, __u16 vid);
|
||||||
|
+extern struct net_bridge_fdb_entry *br_fdb_has_entry(struct net_device *dev,
|
||||||
|
+ const char *addr,
|
||||||
|
+ __u16 vid);
|
||||||
|
+extern void br_fdb_update_register_notify(struct notifier_block *nb);
|
||||||
|
+extern void br_fdb_update_unregister_notify(struct notifier_block *nb);
|
||||||
|
+
|
||||||
|
+typedef struct net_bridge_port *br_port_dev_get_hook_t(struct net_device *dev,
|
||||||
|
+ struct sk_buff *skb,
|
||||||
|
+ unsigned char *addr,
|
||||||
|
+ unsigned int cookie);
|
||||||
|
+extern br_port_dev_get_hook_t __rcu *br_port_dev_get_hook;
|
||||||
|
+
|
||||||
|
+#define BR_FDB_EVENT_ADD 0x01
|
||||||
|
+#define BR_FDB_EVENT_DEL 0x02
|
||||||
|
+
|
||||||
|
+struct br_fdb_event {
|
||||||
|
+ struct net_device *dev;
|
||||||
|
+ unsigned char addr[6];
|
||||||
|
+ unsigned char is_local;
|
||||||
|
+ struct net_bridge *br;
|
||||||
|
+ struct net_device *orig_dev;
|
||||||
|
+};
|
||||||
|
+extern void br_fdb_register_notify(struct notifier_block *nb);
|
||||||
|
+extern void br_fdb_unregister_notify(struct notifier_block *nb);
|
||||||
|
+
|
||||||
|
+typedef struct net_bridge_port *br_get_dst_hook_t(
|
||||||
|
+ const struct net_bridge_port *src,
|
||||||
|
+ struct sk_buff **skb);
|
||||||
|
+extern br_get_dst_hook_t __rcu *br_get_dst_hook;
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--- a/include/linux/if_vlan.h
|
||||||
|
+++ b/include/linux/if_vlan.h
|
||||||
|
@@ -222,7 +222,28 @@ extern void vlan_vids_del_by_dev(struct
|
||||||
|
|
||||||
|
extern bool vlan_uses_dev(const struct net_device *dev);
|
||||||
|
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+extern void __vlan_dev_update_accel_stats(struct net_device *dev,
|
||||||
|
+ struct rtnl_link_stats64 *stats);
|
||||||
|
+extern u16 vlan_dev_get_egress_prio(struct net_device *dev, u32 skb_prio);
|
||||||
|
+extern struct net_device *vlan_dev_next_dev(const struct net_device *dev);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
#else
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+static inline void __vlan_dev_update_accel_stats(struct net_device *dev,
|
||||||
|
+ struct rtnl_link_stats64 *stats)
|
||||||
|
+{
|
||||||
|
+
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline u16 vlan_dev_get_egress_prio(struct net_device *dev,
|
||||||
|
+ u32 skb_prio)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
static inline struct net_device *
|
||||||
|
__vlan_find_dev_deep_rcu(struct net_device *real_dev,
|
||||||
|
__be16 vlan_proto, u16 vlan_id)
|
||||||
|
--- a/include/linux/netdevice.h
|
||||||
|
+++ b/include/linux/netdevice.h
|
||||||
|
@@ -2834,6 +2834,10 @@ enum netdev_cmd {
|
||||||
|
NETDEV_CVLAN_FILTER_DROP_INFO,
|
||||||
|
NETDEV_SVLAN_FILTER_PUSH_INFO,
|
||||||
|
NETDEV_SVLAN_FILTER_DROP_INFO,
|
||||||
|
+ /* QCA NSS ECM Support - Start */
|
||||||
|
+ NETDEV_BR_JOIN,
|
||||||
|
+ NETDEV_BR_LEAVE,
|
||||||
|
+ /* QCA NSS ECM Support - End */
|
||||||
|
};
|
||||||
|
const char *netdev_cmd_to_name(enum netdev_cmd cmd);
|
||||||
|
|
||||||
|
--- a/include/net/ip6_route.h
|
||||||
|
+++ b/include/net/ip6_route.h
|
||||||
|
@@ -211,6 +211,11 @@ void rt6_multipath_rebalance(struct fib6
|
||||||
|
void rt6_uncached_list_add(struct rt6_info *rt);
|
||||||
|
void rt6_uncached_list_del(struct rt6_info *rt);
|
||||||
|
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+int rt6_register_notifier(struct notifier_block *nb);
|
||||||
|
+int rt6_unregister_notifier(struct notifier_block *nb);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
static inline const struct rt6_info *skb_rt6_info(const struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
const struct dst_entry *dst = skb_dst(skb);
|
||||||
|
--- a/include/net/neighbour.h
|
||||||
|
+++ b/include/net/neighbour.h
|
||||||
|
@@ -574,4 +574,15 @@ static inline void neigh_update_is_route
|
||||||
|
*notify = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+struct neigh_mac_update {
|
||||||
|
+ unsigned char old_mac[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
|
||||||
|
+ unsigned char update_mac[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+extern void neigh_mac_update_register_notify(struct notifier_block *nb);
|
||||||
|
+extern void neigh_mac_update_unregister_notify(struct notifier_block *nb);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--- a/include/net/route.h
|
||||||
|
+++ b/include/net/route.h
|
||||||
|
@@ -234,6 +234,11 @@ struct rtable *rt_dst_alloc(struct net_d
|
||||||
|
bool nopolicy, bool noxfrm);
|
||||||
|
struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt);
|
||||||
|
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+int ip_rt_register_notifier(struct notifier_block *nb);
|
||||||
|
+int ip_rt_unregister_notifier(struct notifier_block *nb);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
struct in_ifaddr;
|
||||||
|
void fib_add_ifaddr(struct in_ifaddr *);
|
||||||
|
void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
|
||||||
|
--- a/net/bridge/br_fdb.c
|
||||||
|
+++ b/net/bridge/br_fdb.c
|
||||||
|
@@ -38,6 +38,35 @@ static int fdb_insert(struct net_bridge
|
||||||
|
static void fdb_notify(struct net_bridge *br,
|
||||||
|
const struct net_bridge_fdb_entry *, int, bool);
|
||||||
|
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+ATOMIC_NOTIFIER_HEAD(br_fdb_notifier_list);
|
||||||
|
+ATOMIC_NOTIFIER_HEAD(br_fdb_update_notifier_list);
|
||||||
|
+
|
||||||
|
+void br_fdb_register_notify(struct notifier_block *nb)
|
||||||
|
+{
|
||||||
|
+ atomic_notifier_chain_register(&br_fdb_notifier_list, nb);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(br_fdb_register_notify);
|
||||||
|
+
|
||||||
|
+void br_fdb_unregister_notify(struct notifier_block *nb)
|
||||||
|
+{
|
||||||
|
+ atomic_notifier_chain_unregister(&br_fdb_notifier_list, nb);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(br_fdb_unregister_notify);
|
||||||
|
+
|
||||||
|
+void br_fdb_update_register_notify(struct notifier_block *nb)
|
||||||
|
+{
|
||||||
|
+ atomic_notifier_chain_register(&br_fdb_update_notifier_list, nb);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(br_fdb_update_register_notify);
|
||||||
|
+
|
||||||
|
+void br_fdb_update_unregister_notify(struct notifier_block *nb)
|
||||||
|
+{
|
||||||
|
+ atomic_notifier_chain_unregister(&br_fdb_update_notifier_list, nb);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(br_fdb_update_unregister_notify);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
int __init br_fdb_init(void)
|
||||||
|
{
|
||||||
|
br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
|
||||||
|
@@ -343,6 +372,7 @@ void br_fdb_cleanup(struct work_struct *
|
||||||
|
unsigned long delay = hold_time(br);
|
||||||
|
unsigned long work_delay = delay;
|
||||||
|
unsigned long now = jiffies;
|
||||||
|
+ u8 mac_addr[6]; /* QCA NSS ECM support */
|
||||||
|
|
||||||
|
/* this part is tricky, in order to avoid blocking learning and
|
||||||
|
* consequently forwarding, we rely on rcu to delete objects with
|
||||||
|
@@ -369,8 +399,15 @@ void br_fdb_cleanup(struct work_struct *
|
||||||
|
work_delay = min(work_delay, this_timer - now);
|
||||||
|
} else {
|
||||||
|
spin_lock_bh(&br->hash_lock);
|
||||||
|
- if (!hlist_unhashed(&f->fdb_node))
|
||||||
|
+ if (!hlist_unhashed(&f->fdb_node)) {
|
||||||
|
+ ether_addr_copy(mac_addr, f->key.addr.addr);
|
||||||
|
fdb_delete(br, f, true);
|
||||||
|
+ /* QCA NSS ECM support - Start */
|
||||||
|
+ atomic_notifier_call_chain(
|
||||||
|
+ &br_fdb_update_notifier_list, 0,
|
||||||
|
+ (void *)mac_addr);
|
||||||
|
+ /* QCA NSS ECM support - End */
|
||||||
|
+ }
|
||||||
|
spin_unlock_bh(&br->hash_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -618,6 +655,12 @@ void br_fdb_update(struct net_bridge *br
|
||||||
|
&fdb->flags)))
|
||||||
|
clear_bit(BR_FDB_ADDED_BY_EXT_LEARN,
|
||||||
|
&fdb->flags);
|
||||||
|
+
|
||||||
|
+ /* QCA NSS ECM support - Start */
|
||||||
|
+ atomic_notifier_call_chain(
|
||||||
|
+ &br_fdb_update_notifier_list,
|
||||||
|
+ 0, (void *)addr);
|
||||||
|
+ /* QCA NSS ECM support - End */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(test_bit(BR_FDB_ADDED_BY_USER, &flags)))
|
||||||
|
@@ -799,6 +842,25 @@ static void fdb_notify(struct net_bridge
|
||||||
|
|
||||||
|
br_offload_fdb_update(fdb);
|
||||||
|
|
||||||
|
+ /* QCA NSS ECM support - Start */
|
||||||
|
+ if (fdb->dst) {
|
||||||
|
+ int event;
|
||||||
|
+ struct br_fdb_event fdb_event;
|
||||||
|
+
|
||||||
|
+ if (type == RTM_NEWNEIGH)
|
||||||
|
+ event = BR_FDB_EVENT_ADD;
|
||||||
|
+ else
|
||||||
|
+ event = BR_FDB_EVENT_DEL;
|
||||||
|
+
|
||||||
|
+ fdb_event.dev = fdb->dst->dev;
|
||||||
|
+ ether_addr_copy(fdb_event.addr, fdb->key.addr.addr);
|
||||||
|
+ fdb_event.is_local = test_bit(BR_FDB_LOCAL, &fdb->flags);
|
||||||
|
+ atomic_notifier_call_chain(&br_fdb_notifier_list,
|
||||||
|
+ event,
|
||||||
|
+ (void *)&fdb_event);
|
||||||
|
+ }
|
||||||
|
+ /* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
if (swdev_notify)
|
||||||
|
br_switchdev_fdb_notify(br, fdb, type);
|
||||||
|
|
||||||
|
@@ -1382,3 +1444,62 @@ void br_fdb_clear_offload(const struct n
|
||||||
|
spin_unlock_bh(&p->br->hash_lock);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(br_fdb_clear_offload);
|
||||||
|
+
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+/* Refresh FDB entries for bridge packets being forwarded by offload engines */
|
||||||
|
+void br_refresh_fdb_entry(struct net_device *dev, const char *addr)
|
||||||
|
+{
|
||||||
|
+ struct net_bridge_port *p = br_port_get_rcu(dev);
|
||||||
|
+
|
||||||
|
+ if (!p || p->state == BR_STATE_DISABLED)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (!is_valid_ether_addr(addr)) {
|
||||||
|
+ pr_info("bridge: Attempt to refresh with invalid ether address %pM\n",
|
||||||
|
+ addr);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+ br_fdb_update(p->br, p, addr, 0, true);
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(br_refresh_fdb_entry);
|
||||||
|
+
|
||||||
|
+/* Update timestamp of FDB entries for bridge packets being forwarded by offload engines */
|
||||||
|
+void br_fdb_entry_refresh(struct net_device *dev, const char *addr, __u16 vid)
|
||||||
|
+{
|
||||||
|
+ struct net_bridge_fdb_entry *fdb;
|
||||||
|
+ struct net_bridge_port *p = br_port_get_rcu(dev);
|
||||||
|
+
|
||||||
|
+ if (!p || p->state == BR_STATE_DISABLED)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+ fdb = fdb_find_rcu(&p->br->fdb_hash_tbl, addr, vid);
|
||||||
|
+ if (likely(fdb)) {
|
||||||
|
+ fdb->updated = jiffies;
|
||||||
|
+ }
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(br_fdb_entry_refresh);
|
||||||
|
+
|
||||||
|
+/* Look up the MAC address in the device's bridge fdb table */
|
||||||
|
+struct net_bridge_fdb_entry *br_fdb_has_entry(struct net_device *dev,
|
||||||
|
+ const char *addr, __u16 vid)
|
||||||
|
+{
|
||||||
|
+ struct net_bridge_port *p = br_port_get_rcu(dev);
|
||||||
|
+ struct net_bridge_fdb_entry *fdb;
|
||||||
|
+
|
||||||
|
+ if (!p || p->state == BR_STATE_DISABLED)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+ fdb = fdb_find_rcu(&p->br->fdb_hash_tbl, addr, vid);
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+
|
||||||
|
+ return fdb;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(br_fdb_has_entry);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
--- a/net/bridge/br_if.c
|
||||||
|
+++ b/net/bridge/br_if.c
|
||||||
|
@@ -27,6 +27,12 @@
|
||||||
|
#include "br_private.h"
|
||||||
|
#include "br_private_offload.h"
|
||||||
|
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+/* Hook for external forwarding logic */
|
||||||
|
+br_port_dev_get_hook_t __rcu *br_port_dev_get_hook __read_mostly;
|
||||||
|
+EXPORT_SYMBOL_GPL(br_port_dev_get_hook);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Determine initial path cost based on speed.
|
||||||
|
* using recommendations from 802.1d standard
|
||||||
|
@@ -707,6 +713,8 @@ int br_add_if(struct net_bridge *br, str
|
||||||
|
|
||||||
|
kobject_uevent(&p->kobj, KOBJ_ADD);
|
||||||
|
|
||||||
|
+ call_netdevice_notifiers(NETDEV_BR_JOIN, dev); /* QCA NSS ECM support */
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err6:
|
||||||
|
@@ -742,6 +750,8 @@ int br_del_if(struct net_bridge *br, str
|
||||||
|
if (!p || p->br != br)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
+ call_netdevice_notifiers(NETDEV_BR_LEAVE, dev); /* QCA NSS ECM support */
|
||||||
|
+
|
||||||
|
/* Since more than one interface can be attached to a bridge,
|
||||||
|
* there still maybe an alternate path for netconsole to use;
|
||||||
|
* therefore there is no reason for a NETDEV_RELEASE event.
|
||||||
|
@@ -810,3 +820,74 @@ bool br_port_flag_is_set(const struct ne
|
||||||
|
return p->flags & flag;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(br_port_flag_is_set);
|
||||||
|
+
|
||||||
|
+/* API to know if hairpin feature is enabled/disabled on this bridge port */
|
||||||
|
+bool br_is_hairpin_enabled(struct net_device *dev)
|
||||||
|
+{
|
||||||
|
+ struct net_bridge_port *port = br_port_get_check_rcu(dev);
|
||||||
|
+
|
||||||
|
+ if (likely(port))
|
||||||
|
+ return port->flags & BR_HAIRPIN_MODE;
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(br_is_hairpin_enabled);
|
||||||
|
+
|
||||||
|
+/* br_port_dev_get()
|
||||||
|
+ * If a skb is provided, and the br_port_dev_get_hook_t hook exists,
|
||||||
|
+ * use that to try and determine the egress port for that skb.
|
||||||
|
+ * If not, or no egress port could be determined, use the given addr
|
||||||
|
+ * to identify the port to which it is reachable,
|
||||||
|
+ * returing a reference to the net device associated with that port.
|
||||||
|
+ *
|
||||||
|
+ * NOTE: Return NULL if given dev is not a bridge or the mac has no
|
||||||
|
+ * associated port.
|
||||||
|
+ */
|
||||||
|
+struct net_device *br_port_dev_get(struct net_device *dev, unsigned char *addr,
|
||||||
|
+ struct sk_buff *skb,
|
||||||
|
+ unsigned int cookie)
|
||||||
|
+{
|
||||||
|
+ struct net_bridge_fdb_entry *fdbe;
|
||||||
|
+ struct net_bridge *br;
|
||||||
|
+ struct net_device *netdev = NULL;
|
||||||
|
+
|
||||||
|
+ /* Is this a bridge? */
|
||||||
|
+ if (!(dev->priv_flags & IFF_EBRIDGE))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+
|
||||||
|
+ /* If the hook exists and the skb isn't NULL, try and get the port */
|
||||||
|
+ if (skb) {
|
||||||
|
+ br_port_dev_get_hook_t *port_dev_get_hook;
|
||||||
|
+
|
||||||
|
+ port_dev_get_hook = rcu_dereference(br_port_dev_get_hook);
|
||||||
|
+ if (port_dev_get_hook) {
|
||||||
|
+ struct net_bridge_port *pdst =
|
||||||
|
+ __br_get(port_dev_get_hook, NULL, dev, skb,
|
||||||
|
+ addr, cookie);
|
||||||
|
+ if (pdst) {
|
||||||
|
+ dev_hold(pdst->dev);
|
||||||
|
+ netdev = pdst->dev;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Either there is no hook, or can't
|
||||||
|
+ * determine the port to use - fall back to using FDB
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ br = netdev_priv(dev);
|
||||||
|
+
|
||||||
|
+ /* Lookup the fdb entry and get reference to the port dev */
|
||||||
|
+ fdbe = br_fdb_find_rcu(br, addr, 0);
|
||||||
|
+ if (fdbe && fdbe->dst) {
|
||||||
|
+ netdev = fdbe->dst->dev; /* port device */
|
||||||
|
+ dev_hold(netdev);
|
||||||
|
+ }
|
||||||
|
+out:
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+ return netdev;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(br_port_dev_get);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
--- a/net/bridge/br_private.h
|
||||||
|
+++ b/net/bridge/br_private.h
|
||||||
|
@@ -2122,4 +2122,9 @@ void br_do_proxy_suppress_arp(struct sk_
|
||||||
|
void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
|
||||||
|
u16 vid, struct net_bridge_port *p, struct nd_msg *msg);
|
||||||
|
struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *m);
|
||||||
|
+
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+#define __br_get(__hook, __default, __args ...) \
|
||||||
|
+ (__hook ? (__hook(__args)) : (__default))
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
#endif
|
||||||
|
--- a/net/core/neighbour.c
|
||||||
|
+++ b/net/core/neighbour.c
|
||||||
|
@@ -1204,7 +1204,21 @@ static void neigh_update_hhs(struct neig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* QCA NSS ECM support - start */
|
||||||
|
+ATOMIC_NOTIFIER_HEAD(neigh_mac_update_notifier_list);
|
||||||
|
+
|
||||||
|
+void neigh_mac_update_register_notify(struct notifier_block *nb)
|
||||||
|
+{
|
||||||
|
+ atomic_notifier_chain_register(&neigh_mac_update_notifier_list, nb);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(neigh_mac_update_register_notify);
|
||||||
|
|
||||||
|
+void neigh_mac_update_unregister_notify(struct notifier_block *nb)
|
||||||
|
+{
|
||||||
|
+ atomic_notifier_chain_unregister(&neigh_mac_update_notifier_list, nb);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(neigh_mac_update_unregister_notify);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
|
||||||
|
/* Generic update routine.
|
||||||
|
-- lladdr is new lladdr or NULL, if it is not supplied.
|
||||||
|
@@ -1235,6 +1249,7 @@ static int __neigh_update(struct neighbo
|
||||||
|
int notify = 0;
|
||||||
|
struct net_device *dev;
|
||||||
|
int update_isrouter = 0;
|
||||||
|
+ struct neigh_mac_update nmu; /* QCA NSS ECM support */
|
||||||
|
|
||||||
|
trace_neigh_update(neigh, lladdr, new, flags, nlmsg_pid);
|
||||||
|
|
||||||
|
@@ -1249,6 +1264,8 @@ static int __neigh_update(struct neighbo
|
||||||
|
new = old;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
+ memset(&nmu, 0, sizeof(struct neigh_mac_update)); /* QCA NSS ECM support */
|
||||||
|
+
|
||||||
|
if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
|
||||||
|
(old & (NUD_NOARP | NUD_PERMANENT)))
|
||||||
|
goto out;
|
||||||
|
@@ -1286,6 +1303,11 @@ static int __neigh_update(struct neighbo
|
||||||
|
- compare new & old
|
||||||
|
- if they are different, check override flag
|
||||||
|
*/
|
||||||
|
+ /* QCA NSS ECM update - Start */
|
||||||
|
+ memcpy(nmu.old_mac, neigh->ha, dev->addr_len);
|
||||||
|
+ memcpy(nmu.update_mac, lladdr, dev->addr_len);
|
||||||
|
+ /* QCA NSS ECM update - End */
|
||||||
|
+
|
||||||
|
if ((old & NUD_VALID) &&
|
||||||
|
!memcmp(lladdr, neigh->ha, dev->addr_len))
|
||||||
|
lladdr = neigh->ha;
|
||||||
|
@@ -1408,8 +1430,11 @@ out:
|
||||||
|
if (((new ^ old) & NUD_PERMANENT) || ext_learn_change)
|
||||||
|
neigh_update_gc_list(neigh);
|
||||||
|
|
||||||
|
- if (notify)
|
||||||
|
+ if (notify) {
|
||||||
|
neigh_update_notify(neigh, nlmsg_pid);
|
||||||
|
+ atomic_notifier_call_chain(&neigh_mac_update_notifier_list, 0,
|
||||||
|
+ (struct neigh_mac_update *)&nmu); /* QCA NSS ECM support */
|
||||||
|
+ }
|
||||||
|
|
||||||
|
trace_neigh_update_done(neigh, err);
|
||||||
|
|
||||||
|
--- a/net/ipv4/fib_trie.c
|
||||||
|
+++ b/net/ipv4/fib_trie.c
|
||||||
|
@@ -1203,6 +1203,9 @@ static bool fib_valid_key_len(u32 key, u
|
||||||
|
static void fib_remove_alias(struct trie *t, struct key_vector *tp,
|
||||||
|
struct key_vector *l, struct fib_alias *old);
|
||||||
|
|
||||||
|
+/* Define route change notification chain. */
|
||||||
|
+static BLOCKING_NOTIFIER_HEAD(iproute_chain); /* QCA NSS ECM support */
|
||||||
|
+
|
||||||
|
/* Caller must hold RTNL. */
|
||||||
|
int fib_table_insert(struct net *net, struct fib_table *tb,
|
||||||
|
struct fib_config *cfg, struct netlink_ext_ack *extack)
|
||||||
|
@@ -1393,6 +1396,9 @@ int fib_table_insert(struct net *net, st
|
||||||
|
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, new_fa->tb_id,
|
||||||
|
&cfg->fc_nlinfo, nlflags);
|
||||||
|
succeeded:
|
||||||
|
+ blocking_notifier_call_chain(&iproute_chain,
|
||||||
|
+ RTM_NEWROUTE, fi);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_remove_new_fa:
|
||||||
|
@@ -1763,6 +1769,9 @@ int fib_table_delete(struct net *net, st
|
||||||
|
if (fa_to_delete->fa_state & FA_S_ACCESSED)
|
||||||
|
rt_cache_flush(cfg->fc_nlinfo.nl_net);
|
||||||
|
|
||||||
|
+ blocking_notifier_call_chain(&iproute_chain,
|
||||||
|
+ RTM_DELROUTE, fa_to_delete->fa_info);
|
||||||
|
+
|
||||||
|
fib_release_info(fa_to_delete->fa_info);
|
||||||
|
alias_free_mem_rcu(fa_to_delete);
|
||||||
|
return 0;
|
||||||
|
@@ -2391,6 +2400,20 @@ void __init fib_trie_init(void)
|
||||||
|
0, SLAB_PANIC | SLAB_ACCOUNT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+int ip_rt_register_notifier(struct notifier_block *nb)
|
||||||
|
+{
|
||||||
|
+ return blocking_notifier_chain_register(&iproute_chain, nb);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(ip_rt_register_notifier);
|
||||||
|
+
|
||||||
|
+int ip_rt_unregister_notifier(struct notifier_block *nb)
|
||||||
|
+{
|
||||||
|
+ return blocking_notifier_chain_unregister(&iproute_chain, nb);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(ip_rt_unregister_notifier);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
struct fib_table *fib_trie_table(u32 id, struct fib_table *alias)
|
||||||
|
{
|
||||||
|
struct fib_table *tb;
|
||||||
|
--- a/include/net/addrconf.h
|
||||||
|
+++ b/include/net/addrconf.h
|
||||||
|
@@ -501,4 +501,9 @@ int if6_proc_init(void);
|
||||||
|
void if6_proc_exit(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+struct net_device *ipv6_dev_find_and_hold(struct net *net, struct in6_addr *addr,
|
||||||
|
+ int strict);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--- a/net/ipv6/route.c
|
||||||
|
+++ b/net/ipv6/route.c
|
||||||
|
@@ -3878,6 +3878,9 @@ out_free:
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Define route change notification chain. */
|
||||||
|
+ATOMIC_NOTIFIER_HEAD(ip6route_chain); /* QCA NSS ECM support */
|
||||||
|
+
|
||||||
|
int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
@@ -3889,6 +3892,10 @@ int ip6_route_add(struct fib6_config *cf
|
||||||
|
return PTR_ERR(rt);
|
||||||
|
|
||||||
|
err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, extack);
|
||||||
|
+ if (!err)
|
||||||
|
+ atomic_notifier_call_chain(&ip6route_chain,
|
||||||
|
+ RTM_NEWROUTE, rt);
|
||||||
|
+
|
||||||
|
fib6_info_release(rt);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
@@ -3910,6 +3917,9 @@ static int __ip6_del_rt(struct fib6_info
|
||||||
|
err = fib6_del(rt, info);
|
||||||
|
spin_unlock_bh(&table->tb6_lock);
|
||||||
|
|
||||||
|
+ if (!err)
|
||||||
|
+ atomic_notifier_call_chain(&ip6route_chain,
|
||||||
|
+ RTM_DELROUTE, rt);
|
||||||
|
out:
|
||||||
|
fib6_info_release(rt);
|
||||||
|
return err;
|
||||||
|
@@ -6352,6 +6362,20 @@ static int ip6_route_dev_notify(struct n
|
||||||
|
return NOTIFY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* QCA NSS ECM support - Start */
|
||||||
|
+int rt6_register_notifier(struct notifier_block *nb)
|
||||||
|
+{
|
||||||
|
+ return atomic_notifier_chain_register(&ip6route_chain, nb);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(rt6_register_notifier);
|
||||||
|
+
|
||||||
|
+int rt6_unregister_notifier(struct notifier_block *nb)
|
||||||
|
+{
|
||||||
|
+ return atomic_notifier_chain_unregister(&ip6route_chain, nb);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(rt6_unregister_notifier);
|
||||||
|
+/* QCA NSS ECM support - End */
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* /proc
|
||||||
|
*/
|
@ -0,0 +1,35 @@
|
|||||||
|
From 9d2a00412fde5f5d7dbd341f42acb6799c2db65c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simon Casey <simon501098c@gmail.com>
|
||||||
|
Date: Wed, 2 Feb 2022 19:30:09 +0100
|
||||||
|
Subject: [PATCH] Update 601-netfilter-export-udp_get_timeouts-function.patch
|
||||||
|
for kernel 5.15
|
||||||
|
|
||||||
|
---
|
||||||
|
include/net/netfilter/nf_conntrack_timeout.h | 1 +
|
||||||
|
net/netfilter/nf_conntrack_proto_udp.c | 3 ++-
|
||||||
|
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/include/net/netfilter/nf_conntrack_timeout.h
|
||||||
|
+++ b/include/net/netfilter/nf_conntrack_timeout.h
|
||||||
|
@@ -123,5 +123,6 @@ static inline void nf_ct_destroy_timeout
|
||||||
|
extern struct nf_ct_timeout *(*nf_ct_timeout_find_get_hook)(struct net *net, const char *name);
|
||||||
|
extern void (*nf_ct_timeout_put_hook)(struct nf_ct_timeout *timeout);
|
||||||
|
#endif
|
||||||
|
+extern unsigned int *udp_get_timeouts(struct net *net);
|
||||||
|
|
||||||
|
#endif /* _NF_CONNTRACK_TIMEOUT_H */
|
||||||
|
--- a/net/netfilter/nf_conntrack_proto_udp.c
|
||||||
|
+++ b/net/netfilter/nf_conntrack_proto_udp.c
|
||||||
|
@@ -29,10 +29,11 @@ static const unsigned int udp_timeouts[U
|
||||||
|
[UDP_CT_REPLIED] = 120*HZ,
|
||||||
|
};
|
||||||
|
|
||||||
|
-static unsigned int *udp_get_timeouts(struct net *net)
|
||||||
|
+unsigned int *udp_get_timeouts(struct net *net)
|
||||||
|
{
|
||||||
|
return nf_udp_pernet(net)->timeouts;
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL(udp_get_timeouts);
|
||||||
|
|
||||||
|
static void udp_error_log(const struct sk_buff *skb,
|
||||||
|
const struct nf_hook_state *state,
|
@ -0,0 +1,602 @@
|
|||||||
|
From ac4b71aecf237fd07a29788706d198b4e36fa660 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simon Casey <simon501098c@gmail.com>
|
||||||
|
Date: Wed, 2 Feb 2022 19:32:54 +0100
|
||||||
|
Subject: [PATCH] Update 602-qca-add-pppoe-offload-support.patch for kernel
|
||||||
|
5.15
|
||||||
|
|
||||||
|
---
|
||||||
|
drivers/net/ppp/ppp_generic.c | 276 +++++++++++++++++++++++++++++++++-
|
||||||
|
drivers/net/ppp/pppoe.c | 82 +++++++++-
|
||||||
|
include/linux/if_pppox.h | 13 ++
|
||||||
|
include/linux/netdevice.h | 19 +++
|
||||||
|
include/linux/ppp_channel.h | 63 +++++++-
|
||||||
|
5 files changed, 445 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/net/ppp/ppp_generic.c
|
||||||
|
+++ b/drivers/net/ppp/ppp_generic.c
|
||||||
|
@@ -48,6 +48,7 @@
|
||||||
|
#include <net/slhc_vj.h>
|
||||||
|
#include <linux/atomic.h>
|
||||||
|
#include <linux/refcount.h>
|
||||||
|
+#include <linux/if_pppox.h>
|
||||||
|
|
||||||
|
#include <linux/nsproxy.h>
|
||||||
|
#include <net/net_namespace.h>
|
||||||
|
@@ -253,6 +254,25 @@ 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);
|
||||||
|
@@ -3450,7 +3470,10 @@ 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);
|
||||||
|
|
||||||
|
mutex_lock(&pn->all_ppp_mutex);
|
||||||
|
@@ -3482,13 +3505,40 @@ ppp_connect_channel(struct channel *pch,
|
||||||
|
++ppp->n_channels;
|
||||||
|
pch->ppp = ppp;
|
||||||
|
refcount_inc(&ppp->file.refcnt);
|
||||||
|
+
|
||||||
|
+ /* Set the netdev priv flag if the prototype
|
||||||
|
+ * is L2TP or PPTP. Return success in all cases
|
||||||
|
+ */
|
||||||
|
+ if (!pch->chan)
|
||||||
|
+ goto out2;
|
||||||
|
+
|
||||||
|
+ ppp_proto = ppp_channel_get_protocol(pch->chan);
|
||||||
|
+ if (ppp_proto == PX_PROTO_PPTP) {
|
||||||
|
+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_PPTP;
|
||||||
|
+ } else if (ppp_proto == PX_PROTO_OL2TP) {
|
||||||
|
+ version = ppp_channel_get_proto_version(pch->chan);
|
||||||
|
+ if (version == 2)
|
||||||
|
+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_L2TPV2;
|
||||||
|
+ else if (version == 3)
|
||||||
|
+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_L2TPV3;
|
||||||
|
+ }
|
||||||
|
+ notify = 1;
|
||||||
|
+
|
||||||
|
+ out2:
|
||||||
|
ppp_unlock(ppp);
|
||||||
|
ret = 0;
|
||||||
|
-
|
||||||
|
outl:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -3506,6 +3556,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);
|
||||||
|
@@ -3585,6 +3642,222 @@ 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_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);
|
||||||
|
+
|
||||||
|
+/* 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);
|
||||||
|
+
|
||||||
|
+/* 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);
|
||||||
|
@@ -3601,6 +3874,7 @@ EXPORT_SYMBOL(ppp_input_error);
|
||||||
|
EXPORT_SYMBOL(ppp_output_wakeup);
|
||||||
|
EXPORT_SYMBOL(ppp_register_compressor);
|
||||||
|
EXPORT_SYMBOL(ppp_unregister_compressor);
|
||||||
|
+EXPORT_SYMBOL(ppp_update_stats);
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS_CHARDEV(PPP_MAJOR, 0);
|
||||||
|
MODULE_ALIAS_RTNL_LINK("ppp");
|
||||||
|
--- a/drivers/net/ppp/pppoe.c
|
||||||
|
+++ b/drivers/net/ppp/pppoe.c
|
||||||
|
@@ -62,6 +62,7 @@
|
||||||
|
#include <linux/inetdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
+#include <linux/if_arp.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <linux/if_pppox.h>
|
||||||
|
@@ -87,7 +88,7 @@
|
||||||
|
static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
|
||||||
|
|
||||||
|
static const struct proto_ops pppoe_ops;
|
||||||
|
-static const struct ppp_channel_ops pppoe_chan_ops;
|
||||||
|
+static const struct pppoe_channel_ops pppoe_chan_ops;
|
||||||
|
|
||||||
|
/* per-net private data for this module */
|
||||||
|
static unsigned int pppoe_net_id __read_mostly;
|
||||||
|
@@ -692,7 +693,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 +996,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.get_channel_protocol = pppoe_get_channel_protocol,
|
||||||
|
+ .ops.hold = pppoe_hold_chan,
|
||||||
|
+ .ops.release = pppoe_release_chan,
|
||||||
|
+ .ops.fill_forward_path = pppoe_fill_forward_path,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pppoe_recvmsg(struct socket *sock, struct msghdr *m,
|
||||||
|
--- a/include/linux/if_pppox.h
|
||||||
|
+++ b/include/linux/if_pppox.h
|
||||||
|
@@ -93,4 +93,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/netdevice.h
|
||||||
|
+++ b/include/linux/netdevice.h
|
||||||
|
@@ -1659,6 +1659,24 @@ enum netdev_extra_priv_flags {
|
||||||
|
IFF_NO_IP_ALIGN = 1<<0,
|
||||||
|
};
|
||||||
|
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * enum netdev_priv_flags_ext - &struct net_device priv_flags_ext
|
||||||
|
+ *
|
||||||
|
+ * These flags are used to check for device type and can be
|
||||||
|
+ * set and used by the drivers
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+enum netdev_priv_flags_ext {
|
||||||
|
+ IFF_EXT_TUN_TAP = 1<<0,
|
||||||
|
+ IFF_EXT_PPP_L2TPV2 = 1<<1,
|
||||||
|
+ IFF_EXT_PPP_L2TPV3 = 1<<2,
|
||||||
|
+ IFF_EXT_PPP_PPTP = 1<<3,
|
||||||
|
+ IFF_EXT_GRE_V4_TAP = 1<<4,
|
||||||
|
+ IFF_EXT_GRE_V6_TAP = 1<<5,
|
||||||
|
+ IFF_EXT_IFB = 1<<6,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
#define IFF_802_1Q_VLAN IFF_802_1Q_VLAN
|
||||||
|
#define IFF_EBRIDGE IFF_EBRIDGE
|
||||||
|
#define IFF_BONDING IFF_BONDING
|
||||||
|
@@ -1994,6 +2012,7 @@ struct net_device {
|
||||||
|
unsigned int flags;
|
||||||
|
unsigned int priv_flags;
|
||||||
|
unsigned int extra_priv_flags;
|
||||||
|
+ unsigned int priv_flags_ext;
|
||||||
|
const struct net_device_ops *netdev_ops;
|
||||||
|
int ifindex;
|
||||||
|
unsigned short gflags;
|
||||||
|
--- a/include/linux/ppp_channel.h
|
||||||
|
+++ b/include/linux/ppp_channel.h
|
||||||
|
@@ -19,6 +19,10 @@
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/poll.h>
|
||||||
|
#include <net/net_namespace.h>
|
||||||
|
+#include <linux/notifier.h>
|
||||||
|
+
|
||||||
|
+#define PPP_CHANNEL_DISCONNECT 0
|
||||||
|
+#define PPP_CHANNEL_CONNECT 1
|
||||||
|
|
||||||
|
struct ppp_channel;
|
||||||
|
|
||||||
|
@@ -28,9 +32,19 @@ 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);
|
||||||
|
+ /* 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 *);
|
||||||
|
int (*fill_forward_path)(struct net_device_path_ctx *,
|
||||||
|
- struct net_device_path *,
|
||||||
|
- const struct ppp_channel *);
|
||||||
|
+ struct net_device_path *,
|
||||||
|
+ const struct ppp_channel *);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ppp_channel {
|
||||||
|
@@ -74,6 +88,51 @@ 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 *);
|
||||||
|
|
||||||
|
+/* 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);
|
||||||
|
+
|
||||||
|
+/* Test if the ppp device is a multi-link ppp device */
|
||||||
|
+extern int ppp_is_multilink(struct net_device *dev);
|
||||||
|
+
|
||||||
|
+/* 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);
|
||||||
|
+
|
||||||
|
+/* 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);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* SMP locking notes:
|
||||||
|
* The channel code must ensure that when it calls ppp_unregister_channel,
|
@ -0,0 +1,75 @@
|
|||||||
|
From 03a9fdd468ba3635b26477ca80a1599c29341aed Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simon Casey <simon501098c@gmail.com>
|
||||||
|
Date: Wed, 2 Feb 2022 19:35:35 +0100
|
||||||
|
Subject: [PATCH] Update
|
||||||
|
603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch for kernel
|
||||||
|
5.15
|
||||||
|
|
||||||
|
Also combined with 604-net-core-Replace-nss-keyword-with-offload.patch that just changes
|
||||||
|
variable names created with 603.
|
||||||
|
---
|
||||||
|
include/linux/skbuff.h | 2 ++
|
||||||
|
include/net/sch_generic.h | 34 ++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 36 insertions(+)
|
||||||
|
|
||||||
|
--- a/include/linux/skbuff.h
|
||||||
|
+++ b/include/linux/skbuff.h
|
||||||
|
@@ -652,6 +652,7 @@ typedef unsigned char *sk_buff_data_t;
|
||||||
|
* @offload_fwd_mark: Packet was L2-forwarded in hardware
|
||||||
|
* @offload_l3_fwd_mark: Packet was L3-forwarded in hardware
|
||||||
|
* @tc_skip_classify: do not classify packet. set by IFB device
|
||||||
|
+ * @tc_skip_classify_offload: do not classify packet set by offload IFB device
|
||||||
|
* @tc_at_ingress: used within tc_classify to distinguish in/egress
|
||||||
|
* @redirected: packet was redirected by packet classifier
|
||||||
|
* @from_ingress: packet was redirected from the ingress path
|
||||||
|
@@ -867,6 +868,7 @@ struct sk_buff {
|
||||||
|
#ifdef CONFIG_NET_CLS_ACT
|
||||||
|
__u8 tc_skip_classify:1;
|
||||||
|
__u8 tc_at_ingress:1;
|
||||||
|
+ __u8 tc_skip_classify_offload:1;
|
||||||
|
#endif
|
||||||
|
__u8 redirected:1;
|
||||||
|
#ifdef CONFIG_NET_REDIRECT
|
||||||
|
--- a/include/net/sch_generic.h
|
||||||
|
+++ b/include/net/sch_generic.h
|
||||||
|
@@ -739,6 +739,40 @@ static inline bool skb_skip_tc_classify(
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Set skb classify bit field.
|
||||||
|
+ */
|
||||||
|
+static inline void skb_set_tc_classify_offload(struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+#ifdef CONFIG_NET_CLS_ACT
|
||||||
|
+ skb->tc_skip_classify_offload = 1;
|
||||||
|
+#endif
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Clear skb classify bit field.
|
||||||
|
+ */
|
||||||
|
+static inline void skb_clear_tc_classify_offload(struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+#ifdef CONFIG_NET_CLS_ACT
|
||||||
|
+ skb->tc_skip_classify_offload = 0;
|
||||||
|
+#endif
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Skip skb processing if sent from ifb dev.
|
||||||
|
+ */
|
||||||
|
+static inline bool skb_skip_tc_classify_offload(struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+#ifdef CONFIG_NET_CLS_ACT
|
||||||
|
+ if (skb->tc_skip_classify_offload) {
|
||||||
|
+ skb_clear_tc_classify_offload(skb);
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Reset all TX qdiscs greater than index of a device. */
|
||||||
|
static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i)
|
||||||
|
{
|
@ -0,0 +1,95 @@
|
|||||||
|
From 3c17a0e1112be70071e98d5208da5b55dcec20a6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simon Casey <simon501098c@gmail.com>
|
||||||
|
Date: Wed, 2 Feb 2022 19:37:29 +0100
|
||||||
|
Subject: [PATCH] Update 605-qca-add-add-nss-bridge-mgr-support.patch for
|
||||||
|
kernel 5.15
|
||||||
|
|
||||||
|
---
|
||||||
|
include/linux/if_bridge.h | 4 ++++
|
||||||
|
net/bridge/br_fdb.c | 25 +++++++++++++++++++++----
|
||||||
|
2 files changed, 25 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
--- a/include/linux/if_bridge.h
|
||||||
|
+++ b/include/linux/if_bridge.h
|
||||||
|
@@ -236,4 +236,8 @@ typedef struct net_bridge_port *br_get_d
|
||||||
|
extern br_get_dst_hook_t __rcu *br_get_dst_hook;
|
||||||
|
/* QCA NSS ECM support - End */
|
||||||
|
|
||||||
|
+/* QCA NSS bridge-mgr support - Start */
|
||||||
|
+extern struct net_device *br_fdb_bridge_dev_get_and_hold(struct net_bridge *br);
|
||||||
|
+/* QCA NSS bridge-mgr support - End */
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--- a/net/bridge/br_fdb.c
|
||||||
|
+++ b/net/bridge/br_fdb.c
|
||||||
|
@@ -67,6 +67,15 @@ void br_fdb_update_unregister_notify(str
|
||||||
|
EXPORT_SYMBOL_GPL(br_fdb_update_unregister_notify);
|
||||||
|
/* QCA NSS ECM support - End */
|
||||||
|
|
||||||
|
+/* QCA NSS bridge-mgr support - Start */
|
||||||
|
+struct net_device *br_fdb_bridge_dev_get_and_hold(struct net_bridge *br)
|
||||||
|
+{
|
||||||
|
+ dev_hold(br->dev);
|
||||||
|
+ return br->dev;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(br_fdb_bridge_dev_get_and_hold);
|
||||||
|
+/* QCA NSS bridge-mgr support - End */
|
||||||
|
+
|
||||||
|
int __init br_fdb_init(void)
|
||||||
|
{
|
||||||
|
br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
|
||||||
|
@@ -372,7 +381,7 @@ void br_fdb_cleanup(struct work_struct *
|
||||||
|
unsigned long delay = hold_time(br);
|
||||||
|
unsigned long work_delay = delay;
|
||||||
|
unsigned long now = jiffies;
|
||||||
|
- u8 mac_addr[6]; /* QCA NSS ECM support */
|
||||||
|
+ struct br_fdb_event fdb_event; /* QCA NSS bridge-mgr support */
|
||||||
|
|
||||||
|
/* this part is tricky, in order to avoid blocking learning and
|
||||||
|
* consequently forwarding, we rely on rcu to delete objects with
|
||||||
|
@@ -400,12 +409,13 @@ void br_fdb_cleanup(struct work_struct *
|
||||||
|
} else {
|
||||||
|
spin_lock_bh(&br->hash_lock);
|
||||||
|
if (!hlist_unhashed(&f->fdb_node)) {
|
||||||
|
- ether_addr_copy(mac_addr, f->key.addr.addr);
|
||||||
|
+ memset(&fdb_event, 0, sizeof(fdb_event));
|
||||||
|
+ ether_addr_copy(fdb_event.addr, f->key.addr.addr);
|
||||||
|
fdb_delete(br, f, true);
|
||||||
|
/* QCA NSS ECM support - Start */
|
||||||
|
atomic_notifier_call_chain(
|
||||||
|
&br_fdb_update_notifier_list, 0,
|
||||||
|
- (void *)mac_addr);
|
||||||
|
+ (void *)&fdb_event);
|
||||||
|
/* QCA NSS ECM support - End */
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&br->hash_lock);
|
||||||
|
@@ -623,6 +633,7 @@ void br_fdb_update(struct net_bridge *br
|
||||||
|
const unsigned char *addr, u16 vid, unsigned long flags)
|
||||||
|
{
|
||||||
|
struct net_bridge_fdb_entry *fdb;
|
||||||
|
+ struct br_fdb_event fdb_event; /* QCA NSS bridge-mgr support */
|
||||||
|
|
||||||
|
/* some users want to always flood. */
|
||||||
|
if (hold_time(br) == 0)
|
||||||
|
@@ -648,6 +659,12 @@ void br_fdb_update(struct net_bridge *br
|
||||||
|
if (unlikely(source != READ_ONCE(fdb->dst) &&
|
||||||
|
!test_bit(BR_FDB_STICKY, &fdb->flags))) {
|
||||||
|
br_switchdev_fdb_notify(br, fdb, RTM_DELNEIGH);
|
||||||
|
+ /* QCA NSS bridge-mgr support - Start */
|
||||||
|
+ ether_addr_copy(fdb_event.addr, addr);
|
||||||
|
+ fdb_event.br = br;
|
||||||
|
+ fdb_event.orig_dev = READ_ONCE(fdb->dst->dev);
|
||||||
|
+ fdb_event.dev = source->dev;
|
||||||
|
+ /* QCA NSS bridge-mgr support - End */
|
||||||
|
WRITE_ONCE(fdb->dst, source);
|
||||||
|
fdb_modified = true;
|
||||||
|
/* Take over HW learned entry */
|
||||||
|
@@ -659,7 +676,7 @@ void br_fdb_update(struct net_bridge *br
|
||||||
|
/* QCA NSS ECM support - Start */
|
||||||
|
atomic_notifier_call_chain(
|
||||||
|
&br_fdb_update_notifier_list,
|
||||||
|
- 0, (void *)addr);
|
||||||
|
+ 0, (void *)&fdb_event);
|
||||||
|
/* QCA NSS ECM support - End */
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
|||||||
|
--- a/drivers/net/bonding/bond_main.c
|
||||||
|
+++ b/drivers/net/bonding/bond_main.c
|
||||||
|
@@ -249,6 +249,9 @@ static const struct flow_dissector_key f
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* QCA NSS bonding support */
|
||||||
|
+static unsigned long bond_id_mask = 0xFFFFFFF0;
|
||||||
|
+
|
||||||
|
static struct flow_dissector flow_keys_bonding __read_mostly;
|
||||||
|
|
||||||
|
/*-------------------------- Forward declarations ---------------------------*/
|
||||||
|
@@ -4060,6 +4063,23 @@ static int bond_get_lowest_level_rcu(str
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+/* QCA NSS bonding support */
|
||||||
|
+int bond_get_id(struct net_device *bond_dev)
|
||||||
|
+{
|
||||||
|
+ struct bonding *bond;
|
||||||
|
+ int bond_id = 0;
|
||||||
|
+
|
||||||
|
+ if (!((bond_dev->priv_flags & IFF_BONDING) &&
|
||||||
|
+ (bond_dev->flags & IFF_MASTER)))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ bond = netdev_priv(bond_dev);
|
||||||
|
+ bond_id = bond->id;
|
||||||
|
+
|
||||||
|
+ return bond_id;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(bond_get_id);
|
||||||
|
+
|
||||||
|
static void bond_get_stats(struct net_device *bond_dev,
|
||||||
|
struct rtnl_link_stats64 *stats)
|
||||||
|
{
|
||||||
|
@@ -5392,6 +5412,10 @@ static void bond_destructor(struct net_d
|
||||||
|
|
||||||
|
if (bond->rr_tx_counter)
|
||||||
|
free_percpu(bond->rr_tx_counter);
|
||||||
|
+
|
||||||
|
+ /* QCA NSS bonding support */
|
||||||
|
+ if (bond->id != (~0U))
|
||||||
|
+ clear_bit(bond->id, &bond_id_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bond_setup(struct net_device *bond_dev)
|
||||||
|
@@ -5969,7 +5993,14 @@ int bond_create(struct net *net, const c
|
||||||
|
|
||||||
|
bond_work_init_all(bond);
|
||||||
|
|
||||||
|
- rtnl_unlock();
|
||||||
|
+ /* QCA NSS bonding support */
|
||||||
|
+ bond->id = ~0U;
|
||||||
|
+ if (bond_id_mask != (~0UL)) {
|
||||||
|
+ bond->id = (u32)ffz(bond_id_mask);
|
||||||
|
+ set_bit(bond->id, &bond_id_mask);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rtnl_unlock();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/include/net/bonding.h
|
||||||
|
+++ b/include/net/bonding.h
|
||||||
|
@@ -255,6 +255,7 @@ struct bonding {
|
||||||
|
spinlock_t ipsec_lock;
|
||||||
|
#endif /* CONFIG_XFRM_OFFLOAD */
|
||||||
|
struct bpf_prog *xdp_prog;
|
||||||
|
+ u32 id; /* QCA NSS bonding */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define bond_slave_get_rcu(dev) \
|
||||||
|
@@ -629,6 +630,7 @@ struct bond_net {
|
||||||
|
|
||||||
|
int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, struct slave *slave);
|
||||||
|
netdev_tx_t bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
|
||||||
|
+int bond_get_id(struct net_device *bond_dev); /* QCA NSS bonding support */
|
||||||
|
int bond_create(struct net *net, const char *name);
|
||||||
|
int bond_create_sysfs(struct bond_net *net);
|
||||||
|
void bond_destroy_sysfs(struct bond_net *net);
|
@ -0,0 +1,11 @@
|
|||||||
|
--- a/net/core/dev.c
|
||||||
|
+++ b/net/core/dev.c
|
||||||
|
@@ -1685,7 +1685,7 @@ const char *netdev_cmd_to_name(enum netd
|
||||||
|
N(UDP_TUNNEL_DROP_INFO) N(CHANGE_TX_QUEUE_LEN)
|
||||||
|
N(CVLAN_FILTER_PUSH_INFO) N(CVLAN_FILTER_DROP_INFO)
|
||||||
|
N(SVLAN_FILTER_PUSH_INFO) N(SVLAN_FILTER_DROP_INFO)
|
||||||
|
- N(PRE_CHANGEADDR)
|
||||||
|
+ N(PRE_CHANGEADDR) N(BR_JOIN) N(BR_LEAVE)
|
||||||
|
}
|
||||||
|
#undef N
|
||||||
|
return "UNKNOWN_NETDEV_EVENT";
|
Loading…
Reference in New Issue
Block a user