]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
batman-adv: store hard_iface as iflink private data
authorMatthias Schiffer <mschiffer@universe-factory.net>
Mon, 19 May 2025 20:46:28 +0000 (22:46 +0200)
committerSimon Wunderlich <sw@simonwunderlich.de>
Sat, 31 May 2025 08:41:11 +0000 (10:41 +0200)
By passing the hard_iface to netdev_master_upper_dev_link() as private
data, we can iterate over hardifs of a mesh interface more efficiently
using netdev_for_each_lower_private*() (instead of iterating over the
global hardif list). In addition, this will enable resolving a hardif
from its netdev using netdev_lower_dev_get_private() and getting rid of
the global list altogether in the following patches.

A similar approach can be seen in the bonding driver.

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
13 files changed:
net/batman-adv/bat_algo.c
net/batman-adv/bat_algo.h
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bat_v.c
net/batman-adv/bat_v_elp.c
net/batman-adv/bat_v_ogm.c
net/batman-adv/hard-interface.c
net/batman-adv/main.c
net/batman-adv/mesh-interface.c
net/batman-adv/multicast.c
net/batman-adv/netlink.c
net/batman-adv/originator.c
net/batman-adv/send.c

index c0c982b6f029229ac4462e531ad0bfefc87964dd..49e5861b58ec29fc5ba346ba3f5c8f6f5e3539c7 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/skbuff.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
+#include <linux/types.h>
 #include <net/genetlink.h>
 #include <net/netlink.h>
 #include <uapi/linux/batman_adv.h>
index 2c486374af581f1fe864f1eefadc2523aeadea1c..7ce9abbdb4b47fec99eef5c55090386d95be1010 100644 (file)
 
 #include <linux/netlink.h>
 #include <linux/skbuff.h>
-#include <linux/types.h>
 
 extern char batadv_routing_algo[];
-extern struct list_head batadv_hardif_list;
 
 void batadv_algo_init(void);
 struct batadv_algo_ops *batadv_algo_get(const char *name);
index 458879d21d66331228252a0030796684c0b14d79..54fe38b3b2fd3052cd64b1ed86ee77fcf1dac51c 100644 (file)
@@ -791,6 +791,7 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
        struct batadv_ogm_packet *batadv_ogm_packet;
        struct batadv_hard_iface *primary_if, *tmp_hard_iface;
        int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
+       struct list_head *iter;
        u32 seqno;
        u16 tvlv_len = 0;
        unsigned long send_time;
@@ -847,10 +848,7 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
         * interfaces.
         */
        rcu_read_lock();
-       list_for_each_entry_rcu(tmp_hard_iface, &batadv_hardif_list, list) {
-               if (tmp_hard_iface->mesh_iface != hard_iface->mesh_iface)
-                       continue;
-
+       netdev_for_each_lower_private_rcu(hard_iface->mesh_iface, tmp_hard_iface, iter) {
                if (!kref_get_unless_zero(&tmp_hard_iface->refcount))
                        continue;
 
@@ -1567,6 +1565,7 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
        bool is_my_oldorig = false;
        bool is_my_addr = false;
        bool is_my_orig = false;
+       struct list_head *iter;
 
        ogm_packet = (struct batadv_ogm_packet *)(skb->data + ogm_offset);
        ethhdr = eth_hdr(skb);
@@ -1603,11 +1602,9 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
                   ogm_packet->version, has_directlink_flag);
 
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
-               if (hard_iface->if_status != BATADV_IF_ACTIVE)
-                       continue;
 
-               if (hard_iface->mesh_iface != if_incoming->mesh_iface)
+       netdev_for_each_lower_private_rcu(if_incoming->mesh_iface, hard_iface, iter) {
+               if (hard_iface->if_status != BATADV_IF_ACTIVE)
                        continue;
 
                if (batadv_compare_eth(ethhdr->h_source,
@@ -1668,13 +1665,10 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
                                        if_incoming, BATADV_IF_DEFAULT);
 
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+       netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) {
                if (hard_iface->if_status != BATADV_IF_ACTIVE)
                        continue;
 
-               if (hard_iface->mesh_iface != bat_priv->mesh_iface)
-                       continue;
-
                if (!kref_get_unless_zero(&hard_iface->refcount))
                        continue;
 
@@ -2142,6 +2136,7 @@ batadv_iv_ogm_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
                         struct batadv_hard_iface *single_hardif)
 {
        struct batadv_hard_iface *hard_iface;
+       struct list_head *iter;
        int i_hardif = 0;
        int i_hardif_s = cb->args[0];
        int idx = cb->args[1];
@@ -2158,11 +2153,7 @@ batadv_iv_ogm_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
                                i_hardif++;
                }
        } else {
-               list_for_each_entry_rcu(hard_iface, &batadv_hardif_list,
-                                       list) {
-                       if (hard_iface->mesh_iface != bat_priv->mesh_iface)
-                               continue;
-
+               netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) {
                        if (i_hardif++ < i_hardif_s)
                                continue;
 
index c16c2e60889d2551bd02895226c7aa04e8497e68..de94447142642e2fc2afff9f5b737f97d8a35999 100644 (file)
@@ -212,6 +212,7 @@ batadv_v_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
                    struct batadv_hard_iface *single_hardif)
 {
        struct batadv_hard_iface *hard_iface;
+       struct list_head *iter;
        int i_hardif = 0;
        int i_hardif_s = cb->args[0];
        int idx = cb->args[1];
@@ -227,10 +228,7 @@ batadv_v_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
                                i_hardif++;
                }
        } else {
-               list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
-                       if (hard_iface->mesh_iface != bat_priv->mesh_iface)
-                               continue;
-
+               netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) {
                        if (i_hardif++ < i_hardif_s)
                                continue;
 
index 70d6778da0d7bd9fff9621fe4123de4d970a6f2e..cb16c1ed2a58fcbb2a7b7c682bbc3e58f9c6a7f9 100644 (file)
@@ -35,7 +35,6 @@
 #include <net/cfg80211.h>
 #include <uapi/linux/batadv_packet.h>
 
-#include "bat_algo.h"
 #include "bat_v_ogm.h"
 #include "hard-interface.h"
 #include "log.h"
@@ -472,15 +471,12 @@ void batadv_v_elp_iface_activate(struct batadv_hard_iface *primary_iface,
 void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface)
 {
        struct batadv_hard_iface *hard_iface;
+       struct list_head *iter;
 
        /* update orig field of every elp iface belonging to this mesh */
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
-               if (primary_iface->mesh_iface != hard_iface->mesh_iface)
-                       continue;
-
+       netdev_for_each_lower_private_rcu(primary_iface->mesh_iface, hard_iface, iter)
                batadv_v_elp_iface_activate(primary_iface, hard_iface);
-       }
        rcu_read_unlock();
 }
 
index b86bb647da5b782a48c89e64a7d3cffde4607b25..e3870492dab774be097ed93f65415d116d8851a0 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/random.h>
-#include <linux/rculist.h>
 #include <linux/rcupdate.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
@@ -33,7 +32,6 @@
 #include <linux/workqueue.h>
 #include <uapi/linux/batadv_packet.h>
 
-#include "bat_algo.h"
 #include "hard-interface.h"
 #include "hash.h"
 #include "log.h"
@@ -265,6 +263,7 @@ static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
        struct batadv_ogm2_packet *ogm_packet;
        struct sk_buff *skb, *skb_tmp;
        unsigned char *ogm_buff;
+       struct list_head *iter;
        int ogm_buff_len;
        u16 tvlv_len = 0;
        int ret;
@@ -301,10 +300,7 @@ static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
 
        /* broadcast on every interface */
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
-               if (hard_iface->mesh_iface != bat_priv->mesh_iface)
-                       continue;
-
+       netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) {
                if (!kref_get_unless_zero(&hard_iface->refcount))
                        continue;
 
@@ -859,6 +855,7 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
        struct batadv_hard_iface *hard_iface;
        struct batadv_ogm2_packet *ogm_packet;
        u32 ogm_throughput, link_throughput, path_throughput;
+       struct list_head *iter;
        int ret;
 
        ethhdr = eth_hdr(skb);
@@ -921,13 +918,10 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
                                       BATADV_IF_DEFAULT);
 
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+       netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) {
                if (hard_iface->if_status != BATADV_IF_ACTIVE)
                        continue;
 
-               if (hard_iface->mesh_iface != bat_priv->mesh_iface)
-                       continue;
-
                if (!kref_get_unless_zero(&hard_iface->refcount))
                        continue;
 
index 558d39dffc233020f386625b49b3fb5f0c6af284..bace57e4f9a516331baac04e96abe6ad1b2123dc 100644 (file)
@@ -438,15 +438,13 @@ out:
 }
 
 static struct batadv_hard_iface *
-batadv_hardif_get_active(const struct net_device *mesh_iface)
+batadv_hardif_get_active(struct net_device *mesh_iface)
 {
        struct batadv_hard_iface *hard_iface;
+       struct list_head *iter;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
-               if (hard_iface->mesh_iface != mesh_iface)
-                       continue;
-
+       netdev_for_each_lower_private_rcu(mesh_iface, hard_iface, iter) {
                if (hard_iface->if_status == BATADV_IF_ACTIVE &&
                    kref_get_unless_zero(&hard_iface->refcount))
                        goto out;
@@ -508,19 +506,17 @@ batadv_hardif_is_iface_up(const struct batadv_hard_iface *hard_iface)
 
 static void batadv_check_known_mac_addr(const struct batadv_hard_iface *hard_iface)
 {
-       const struct net_device *mesh_iface = hard_iface->mesh_iface;
+       struct net_device *mesh_iface = hard_iface->mesh_iface;
        const struct batadv_hard_iface *tmp_hard_iface;
+       struct list_head *iter;
 
        if (!mesh_iface)
                return;
 
-       list_for_each_entry(tmp_hard_iface, &batadv_hardif_list, list) {
+       netdev_for_each_lower_private(mesh_iface, tmp_hard_iface, iter) {
                if (tmp_hard_iface == hard_iface)
                        continue;
 
-               if (tmp_hard_iface->mesh_iface != mesh_iface)
-                       continue;
-
                if (tmp_hard_iface->if_status == BATADV_IF_NOT_IN_USE)
                        continue;
 
@@ -545,15 +541,13 @@ static void batadv_hardif_recalc_extra_skbroom(struct net_device *mesh_iface)
        unsigned short lower_headroom = 0;
        unsigned short lower_tailroom = 0;
        unsigned short needed_headroom;
+       struct list_head *iter;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+       netdev_for_each_lower_private_rcu(mesh_iface, hard_iface, iter) {
                if (hard_iface->if_status == BATADV_IF_NOT_IN_USE)
                        continue;
 
-               if (hard_iface->mesh_iface != mesh_iface)
-                       continue;
-
                lower_header_len = max_t(unsigned short, lower_header_len,
                                         hard_iface->net_dev->hard_header_len);
 
@@ -586,17 +580,15 @@ int batadv_hardif_min_mtu(struct net_device *mesh_iface)
 {
        struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
        const struct batadv_hard_iface *hard_iface;
+       struct list_head *iter;
        int min_mtu = INT_MAX;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+       netdev_for_each_lower_private_rcu(mesh_iface, hard_iface, iter) {
                if (hard_iface->if_status != BATADV_IF_ACTIVE &&
                    hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED)
                        continue;
 
-               if (hard_iface->mesh_iface != mesh_iface)
-                       continue;
-
                min_mtu = min_t(int, hard_iface->net_dev->mtu, min_mtu);
        }
        rcu_read_unlock();
@@ -734,7 +726,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
        bat_priv = netdev_priv(hard_iface->mesh_iface);
 
        ret = netdev_master_upper_dev_link(hard_iface->net_dev,
-                                          mesh_iface, NULL, NULL, NULL);
+                                          mesh_iface, hard_iface, NULL, NULL);
        if (ret)
                goto err_dev;
 
@@ -803,18 +795,15 @@ err_dev:
  *
  * Return: number of connected/enslaved hard interfaces
  */
-static size_t batadv_hardif_cnt(const struct net_device *mesh_iface)
+static size_t batadv_hardif_cnt(struct net_device *mesh_iface)
 {
        struct batadv_hard_iface *hard_iface;
+       struct list_head *iter;
        size_t count = 0;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
-               if (hard_iface->mesh_iface != mesh_iface)
-                       continue;
-
+       netdev_for_each_lower_private_rcu(mesh_iface, hard_iface, iter)
                count++;
-       }
        rcu_read_unlock();
 
        return count;
index c0bc755133558ffc488619bea23a5ad7db27dd8b..20346d7b6b69178f7487e99af05851dfebbefb2b 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/printk.h>
-#include <linux/rculist.h>
 #include <linux/rcupdate.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
@@ -303,16 +302,14 @@ void batadv_mesh_free(struct net_device *mesh_iface)
 bool batadv_is_my_mac(struct batadv_priv *bat_priv, const u8 *addr)
 {
        const struct batadv_hard_iface *hard_iface;
+       struct list_head *iter;
        bool is_my_mac = false;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+       netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) {
                if (hard_iface->if_status != BATADV_IF_ACTIVE)
                        continue;
 
-               if (hard_iface->mesh_iface != bat_priv->mesh_iface)
-                       continue;
-
                if (batadv_compare_eth(hard_iface->net_dev->dev_addr, addr)) {
                        is_my_mac = true;
                        break;
index 5bbc366f974d9ad310a323f8d074c7cd663dd2c7..de2c2d9c6e4dba989eeaea12ea997ce462e1c39a 100644 (file)
@@ -1101,9 +1101,9 @@ static void batadv_meshif_destroy_netlink(struct net_device *mesh_iface,
        struct batadv_hard_iface *hard_iface;
        struct batadv_meshif_vlan *vlan;
 
-       list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
-               if (hard_iface->mesh_iface == mesh_iface)
-                       batadv_hardif_disable_interface(hard_iface);
+       while (!list_empty(&mesh_iface->adj_list.lower)) {
+               hard_iface = netdev_adjacent_get_private(mesh_iface->adj_list.lower.next);
+               batadv_hardif_disable_interface(hard_iface);
        }
 
        /* destroy the "untagged" VLAN */
index 5786680aff30c2a478ac78be86c444029f565c32..e8c6b0bf670ff62aee0366d3d07f2cd9e555439d 100644 (file)
@@ -246,15 +246,13 @@ static u8 batadv_mcast_mla_rtr_flags_get(struct batadv_priv *bat_priv,
 static u8 batadv_mcast_mla_forw_flags_get(struct batadv_priv *bat_priv)
 {
        const struct batadv_hard_iface *hard_iface;
+       struct list_head *iter;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+       netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) {
                if (hard_iface->if_status != BATADV_IF_ACTIVE)
                        continue;
 
-               if (hard_iface->mesh_iface != bat_priv->mesh_iface)
-                       continue;
-
                if (hard_iface->net_dev->mtu < IPV6_MIN_MTU) {
                        rcu_read_unlock();
                        return BATADV_NO_FLAGS;
index e7c8f9f2bb1f9093f754b83e57fc57f85f2fadd8..beb181b3a7d88c513561b24c5b19cc884dd73f61 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/if_vlan.h>
 #include <linux/init.h>
 #include <linux/limits.h>
-#include <linux/list.h>
 #include <linux/minmax.h>
 #include <linux/netdevice.h>
 #include <linux/netlink.h>
@@ -968,6 +967,7 @@ batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb)
        struct batadv_priv *bat_priv;
        int portid = NETLINK_CB(cb->skb).portid;
        int skip = cb->args[0];
+       struct list_head *iter;
        int i = 0;
 
        mesh_iface = batadv_netlink_get_meshif(cb);
@@ -979,10 +979,7 @@ batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb)
        rtnl_lock();
        cb->seq = batadv_hardif_generation << 1 | 1;
 
-       list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
-               if (hard_iface->mesh_iface != mesh_iface)
-                       continue;
-
+       netdev_for_each_lower_private(mesh_iface, hard_iface, iter) {
                if (i++ < skip)
                        continue;
 
index d9cfc5c6b20884c8ee6821a6e570091499e5607a..a464ff96b92917c3e9122b850d948a0108602518 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/workqueue.h>
 #include <uapi/linux/batadv_packet.h>
 
-#include "bat_algo.h"
 #include "distributed-arp-table.h"
 #include "fragmentation.h"
 #include "gateway_client.h"
@@ -1208,6 +1207,7 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
        struct batadv_neigh_node *best_neigh_node;
        struct batadv_hard_iface *hard_iface;
        bool changed_ifinfo, changed_neigh;
+       struct list_head *iter;
 
        if (batadv_has_timed_out(orig_node->last_seen,
                                 2 * BATADV_PURGE_TIMEOUT)) {
@@ -1232,13 +1232,10 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
 
        /* ... then for all other interfaces. */
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+       netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) {
                if (hard_iface->if_status != BATADV_IF_ACTIVE)
                        continue;
 
-               if (hard_iface->mesh_iface != bat_priv->mesh_iface)
-                       continue;
-
                if (!kref_get_unless_zero(&hard_iface->refcount))
                        continue;
 
index 9d72f4f15b3d75bca3d1373c3e21c54fbc85ad4a..95849ba004e753c3e5ec7a247766070ed3737249 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/list.h>
 #include <linux/netdevice.h>
 #include <linux/printk.h>
-#include <linux/rculist.h>
 #include <linux/rcupdate.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
@@ -924,6 +923,7 @@ static int __batadv_forw_bcast_packet(struct batadv_priv *bat_priv,
 {
        struct batadv_hard_iface *hard_iface;
        struct batadv_hard_iface *primary_if;
+       struct list_head *iter;
        int ret = NETDEV_TX_OK;
 
        primary_if = batadv_primary_if_get_selected(bat_priv);
@@ -931,10 +931,7 @@ static int __batadv_forw_bcast_packet(struct batadv_priv *bat_priv,
                return NETDEV_TX_BUSY;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
-               if (hard_iface->mesh_iface != bat_priv->mesh_iface)
-                       continue;
-
+       netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) {
                if (!kref_get_unless_zero(&hard_iface->refcount))
                        continue;