kernel: bump 5.15 to 5.15.104
[openwrt/openwrt.git] / target / linux / generic / hack-5.15 / 600-bridge_offload.patch
index 586353816c2edf33d77e75f7cf012db72fda9d39..9d71a741b25d5cf4e97ec68de4028d60a749e399 100644 (file)
@@ -1,10 +1,35 @@
+From 11c3fae5afa6cac444d12622e2cf5af60a99c1ef Mon Sep 17 00:00:00 2001
+From: OpenWrt community <openwrt-devel@lists.openwrt.org>
+Date: Wed, 13 Jul 2022 13:43:15 +0200
+Subject: [PATCH] net/bridge: add bridge offload
+
+---
+ include/linux/if_bridge.h       |   1 +
+ net/bridge/Makefile             |   2 +-
+ net/bridge/br.c                 |   8 +
+ net/bridge/br_device.c          |   2 +
+ net/bridge/br_fdb.c             |   5 +
+ net/bridge/br_forward.c         |   3 +
+ net/bridge/br_if.c              |   6 +-
+ net/bridge/br_input.c           |   5 +
+ net/bridge/br_offload.c         | 438 ++++++++++++++++++++++++++++++++
+ net/bridge/br_private.h         |  22 +-
+ net/bridge/br_private_offload.h |  23 ++
+ net/bridge/br_stp.c             |   3 +
+ net/bridge/br_sysfs_br.c        |  35 +++
+ net/bridge/br_sysfs_if.c        |   2 +
+ net/bridge/br_vlan_tunnel.c     |   3 +
+ 15 files changed, 555 insertions(+), 3 deletions(-)
+ create mode 100644 net/bridge/br_offload.c
+ create mode 100644 net/bridge/br_private_offload.h
+
 --- a/include/linux/if_bridge.h
 +++ b/include/linux/if_bridge.h
-@@ -57,6 +57,7 @@ struct br_ip_list {
- #define BR_MRP_LOST_CONT      BIT(18)
+@@ -59,6 +59,7 @@ struct br_ip_list {
  #define BR_MRP_LOST_IN_CONT   BIT(19)
- #define BR_BPDU_FILTER                BIT(20)
-+#define BR_OFFLOAD            BIT(21)
+ #define BR_TX_FWD_OFFLOAD     BIT(20)
+ #define BR_BPDU_FILTER                BIT(21)
++#define BR_OFFLOAD            BIT(22)
  
  #define BR_DEFAULT_AGEING_TIME        (300 * HZ)
  
@@ -29,7 +54,7 @@
  
  /*
   * Handle changes in state of network devices enslaved to a bridge.
-@@ -332,6 +333,10 @@ static int __init br_init(void)
+@@ -381,6 +382,10 @@ static int __init br_init(void)
        if (err)
                goto err_out;
  
@@ -40,7 +65,7 @@
        err = register_pernet_subsys(&br_net_ops);
        if (err)
                goto err_out1;
-@@ -375,6 +380,8 @@ err_out3:
+@@ -430,6 +435,8 @@ err_out3:
  err_out2:
        unregister_pernet_subsys(&br_net_ops);
  err_out1:
@@ -49,7 +74,7 @@
        br_fdb_fini();
  err_out:
        stp_proto_unregister(&br_stp_proto);
-@@ -396,6 +403,7 @@ static void __exit br_deinit(void)
+@@ -452,6 +459,7 @@ static void __exit br_deinit(void)
  #if IS_ENABLED(CONFIG_ATM_LANE)
        br_fdb_test_addr_hook = NULL;
  #endif
@@ -59,7 +84,7 @@
  
 --- a/net/bridge/br_device.c
 +++ b/net/bridge/br_device.c
-@@ -529,6 +529,8 @@ void br_dev_setup(struct net_device *dev
+@@ -524,6 +524,8 @@ void br_dev_setup(struct net_device *dev
        br->bridge_hello_time = br->hello_time = 2 * HZ;
        br->bridge_forward_delay = br->forward_delay = 15 * HZ;
        br->bridge_ageing_time = br->ageing_time = BR_DEFAULT_AGEING_TIME;
  
  static const struct rhashtable_params br_fdb_rht_params = {
        .head_offset = offsetof(struct net_bridge_fdb_entry, rhnode),
-@@ -513,6 +514,8 @@ static struct net_bridge_fdb_entry *fdb_
+@@ -518,6 +519,8 @@ static struct net_bridge_fdb_entry *fdb_
                fdb->key.vlan_id = vid;
                fdb->flags = flags;
                fdb->updated = fdb->used = jiffies;
                if (rhashtable_lookup_insert_fast(&br->fdb_hash_tbl,
                                                  &fdb->rhnode,
                                                  br_fdb_rht_params)) {
-@@ -734,6 +737,8 @@ static void fdb_notify(struct net_bridge
+@@ -794,6 +797,8 @@ static void fdb_notify(struct net_bridge
        struct sk_buff *skb;
        int err = -ENOBUFS;
  
  
  /*
   * Determine initial path cost based on speed.
-@@ -427,7 +428,7 @@ static struct net_bridge_port *new_nbp(s
+@@ -428,7 +429,7 @@ static struct net_bridge_port *new_nbp(s
        p->path_cost = port_cost(dev);
        p->priority = 0x8000 >> BR_PORT_BITS;
        p->port_no = index;
        br_init_port(p);
        br_set_state(p, BR_STATE_DISABLED);
        br_stp_port_timer_init(p);
-@@ -777,6 +778,9 @@ void br_port_flags_change(struct net_bri
+@@ -771,6 +772,9 @@ void br_port_flags_change(struct net_bri
  
        if (mask & BR_NEIGH_SUPPRESS)
                br_recalculate_neigh_suppress_enabled(br);
  
  static int
  br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
-@@ -162,6 +163,7 @@ int br_handle_frame_finish(struct net *n
+@@ -171,6 +172,7 @@ int br_handle_frame_finish(struct net *n
                        dst->used = now;
                br_forward(dst->dst, skb, local_rcv, false);
        } else {
                if (!mcast_hit)
                        br_flood(br, skb, pkt_type, local_rcv, false);
                else
-@@ -280,6 +282,9 @@ static rx_handler_result_t br_handle_fra
+@@ -304,6 +306,9 @@ static rx_handler_result_t br_handle_fra
        memset(skb->cb, 0, sizeof(struct br_input_skb_cb));
  
        p = br_port_get_rcu(skb->dev);
 +      if (br_offload_input(p, skb))
 +              return RX_HANDLER_CONSUMED;
 +
-       if (p->flags & BR_VLAN_TUNNEL) {
-               if (br_handle_ingress_vlan_tunnel(skb, p,
-                                                 nbp_vlan_group_rcu(p)))
+       if (p->flags & BR_VLAN_TUNNEL)
+               br_handle_ingress_vlan_tunnel(skb, p, nbp_vlan_group_rcu(p));
 --- /dev/null
 +++ b/net/bridge/br_offload.c
-@@ -0,0 +1,436 @@
+@@ -0,0 +1,438 @@
 +// SPDX-License-Identifier: GPL-2.0-only
 +#include <linux/kernel.h>
 +#include <linux/workqueue.h>
 +      vg = nbp_vlan_group_rcu(inp);
 +      vlan = cb->input_vlan_present ? cb->input_vlan_tag : br_get_pvid(vg);
 +      fdb_in = br_fdb_find_rcu(p->br, eth_hdr(skb)->h_source, vlan);
-+      if (!fdb_in)
++      if (!fdb_in || !fdb_in->dst)
 +              goto out;
 +
 +      vg = nbp_vlan_group_rcu(p);
 +      vlan = skb_vlan_tag_present(skb) ? skb_vlan_tag_get_id(skb) : br_get_pvid(vg);
 +      fdb_out = br_fdb_find_rcu(p->br, eth_hdr(skb)->h_dest, vlan);
-+      if (!fdb_out)
++      if (!fdb_out || !fdb_out->dst)
 +              goto out;
 +
 +      br_offload_prepare_key(p, &key, skb);
 +#endif
 +
 +      flow = kmem_cache_alloc(offload_cache, GFP_ATOMIC);
-+      flow->port = fdb_in->dst;
++      flow->port = inp;
 +      memcpy(&flow->key, &key, sizeof(key));
 +
 +#ifdef CONFIG_BRIDGE_VLAN_FILTERING
 +      spin_lock_bh(&offload_lock);
 +      if (!o->enabled ||
 +          atomic_read(&p->offload.rht.nelems) >= p->br->offload_cache_size ||
-+          rhashtable_insert_fast(&flow->port->offload.rht, &flow->node, flow_params)) {
++          rhashtable_insert_fast(&inp->offload.rht, &flow->node, flow_params)) {
 +              kmem_cache_free(offload_cache, flow);
 +              goto out_unlock;
 +      }
 +#ifdef CONFIG_BRIDGE_VLAN_FILTERING
 +              cb->input_vlan_present = key.vlan_present != 0;
 +              cb->input_vlan_tag = key.vlan_tag;
-+              cb->input_ifindex = p->dev->ifindex;
 +#endif
++              cb->input_ifindex = p->dev->ifindex;
 +              goto out;
 +      }
 +
 +}
 +
 +
-+int br_offload_set_cache_size(struct net_bridge *br, unsigned long val)
++int br_offload_set_cache_size(struct net_bridge *br, unsigned long val,
++                             struct netlink_ext_ack *extack)
 +{
 +      br->offload_cache_size = val;
 +      br_offload_check_gc(br);
 +      return 0;
 +}
 +
-+int br_offload_set_cache_reserved(struct net_bridge *br, unsigned long val)
++int br_offload_set_cache_reserved(struct net_bridge *br, unsigned long val,
++                                 struct netlink_ext_ack *extack)
 +{
 +      br->offload_cache_reserved = val;
 +      br_offload_check_gc(br);
 +}
 --- a/net/bridge/br_private.h
 +++ b/net/bridge/br_private.h
-@@ -207,7 +207,13 @@ struct net_bridge_fdb_entry {
+@@ -268,7 +268,13 @@ struct net_bridge_fdb_entry {
        unsigned long                   updated ____cacheline_aligned_in_smp;
        unsigned long                   used;
  
  };
  
  #define MDB_PG_FLAGS_PERMANENT        BIT(0)
-@@ -280,6 +286,12 @@ struct net_bridge_mdb_entry {
+@@ -343,6 +349,12 @@ struct net_bridge_mdb_entry {
        struct rcu_head                 rcu;
  };
  
  struct net_bridge_port {
        struct net_bridge               *br;
        struct net_device               *dev;
-@@ -337,6 +349,7 @@ struct net_bridge_port {
+@@ -403,6 +415,7 @@ struct net_bridge_port {
        u16                             backup_redirected_cnt;
  
        struct bridge_stp_xstats        stp_xstats;
  };
  
  #define kobj_to_brport(obj)   container_of(obj, struct net_bridge_port, kobj)
-@@ -475,6 +488,9 @@ struct net_bridge {
+@@ -519,6 +532,9 @@ struct net_bridge {
        struct kobject                  *ifobj;
        u32                             auto_cnt;
  
 +      u32                             offload_cache_reserved;
 +
  #ifdef CONFIG_NET_SWITCHDEV
-       int offload_fwd_mark;
- #endif
-@@ -501,6 +517,10 @@ struct br_input_skb_cb {
+       /* Counter used to make sure that hardware domains get unique
+        * identifiers in case a bridge spans multiple switchdev instances.
+@@ -553,6 +569,10 @@ struct br_input_skb_cb {
  #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE
        u8 br_netfilter_broute:1;
  #endif
 +      int input_ifindex;
  
  #ifdef CONFIG_NET_SWITCHDEV
-       int offload_fwd_mark;
+       /* Set if TX data plane offloading is used towards at least one
 --- /dev/null
 +++ b/net/bridge/br_private_offload.h
-@@ -0,0 +1,21 @@
+@@ -0,0 +1,23 @@
 +#ifndef __BR_OFFLOAD_H
 +#define __BR_OFFLOAD_H
 +
 +void br_offload_fdb_update(const struct net_bridge_fdb_entry *fdb);
 +int br_offload_init(void);
 +void br_offload_fini(void);
-+int br_offload_set_cache_size(struct net_bridge *br, unsigned long val);
-+int br_offload_set_cache_reserved(struct net_bridge *br, unsigned long val);
++int br_offload_set_cache_size(struct net_bridge *br, unsigned long val,
++                             struct netlink_ext_ack *extack);
++int br_offload_set_cache_reserved(struct net_bridge *br, unsigned long val,
++                                 struct netlink_ext_ack *extack);
 +
 +static inline void br_offload_skb_disable(struct sk_buff *skb)
 +{
  #include "br_private.h"
 +#include "br_private_offload.h"
  
- #define to_bridge(cd) ((struct net_bridge *)netdev_priv(to_net_dev(cd)))
-@@ -842,6 +843,38 @@ static ssize_t vlan_stats_per_port_store
+ /* IMPORTANT: new bridge options must be added with netlink support only
+  *            please do not add new sysfs entries
+@@ -930,6 +931,38 @@ static ssize_t vlan_stats_per_port_store
  static DEVICE_ATTR_RW(vlan_stats_per_port);
  #endif
  
  static struct attribute *bridge_attrs[] = {
        &dev_attr_forward_delay.attr,
        &dev_attr_hello_time.attr,
-@@ -896,6 +929,8 @@ static struct attribute *bridge_attrs[]
+@@ -984,6 +1017,8 @@ static struct attribute *bridge_attrs[]
        &dev_attr_vlan_stats_enabled.attr,
        &dev_attr_vlan_stats_per_port.attr,
  #endif
  
 --- a/net/bridge/br_sysfs_if.c
 +++ b/net/bridge/br_sysfs_if.c
-@@ -234,6 +234,7 @@ BRPORT_ATTR_FLAG(broadcast_flood, BR_BCA
+@@ -241,6 +241,7 @@ BRPORT_ATTR_FLAG(broadcast_flood, BR_BCA
  BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS);
  BRPORT_ATTR_FLAG(isolated, BR_ISOLATED);
  BRPORT_ATTR_FLAG(bpdu_filter, BR_BPDU_FILTER);
  
  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
-@@ -288,6 +289,7 @@ static const struct brport_attribute *br
+@@ -295,6 +296,7 @@ static const struct brport_attribute *br
        &brport_attr_isolated,
        &brport_attr_bpdu_filter,
        &brport_attr_backup_port,
  
  static inline int br_vlan_tunid_cmp(struct rhashtable_compare_arg *arg,
                                    const void *ptr)
-@@ -180,6 +181,7 @@ int br_handle_ingress_vlan_tunnel(struct
+@@ -180,6 +181,7 @@ void br_handle_ingress_vlan_tunnel(struc
        skb_dst_drop(skb);
  
        __vlan_hwaccel_put_tag(skb, p->br->vlan_proto, vlan->vid);
 +      br_offload_skb_disable(skb);
-       return 0;
  }
-@@ -203,6 +205,7 @@ int br_handle_egress_vlan_tunnel(struct
+ int br_handle_egress_vlan_tunnel(struct sk_buff *skb,
+@@ -201,6 +203,7 @@ int br_handle_egress_vlan_tunnel(struct
        if (err)
                return err;