forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 95099d4622f8cb224d94e314c7a8e0df60b13f87
kernel/net/batman-adv/hard-interface.c
....@@ -1,19 +1,7 @@
11 // SPDX-License-Identifier: GPL-2.0
2
-/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors:
2
+/* Copyright (C) 2007-2020 B.A.T.M.A.N. contributors:
33 *
44 * Marek Lindner, Simon Wunderlich
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of version 2 of the GNU General Public
8
- * License as published by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope that it will be useful, but
11
- * WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
175 */
186
197 #include "hard-interface.h"
....@@ -28,6 +16,7 @@
2816 #include <linux/if_ether.h>
2917 #include <linux/kernel.h>
3018 #include <linux/kref.h>
19
+#include <linux/limits.h>
3120 #include <linux/list.h>
3221 #include <linux/mutex.h>
3322 #include <linux/netdevice.h>
....@@ -149,10 +138,10 @@
149138 * @net_dev: the device to check
150139 *
151140 * If the user creates any virtual device on top of a batman-adv interface, it
152
- * is important to prevent this new interface to be used to create a new mesh
153
- * network (this behaviour would lead to a batman-over-batman configuration).
154
- * This function recursively checks all the fathers of the device passed as
155
- * argument looking for a batman-adv soft interface.
141
+ * is important to prevent this new interface from being used to create a new
142
+ * mesh network (this behaviour would lead to a batman-over-batman
143
+ * configuration). This function recursively checks all the fathers of the
144
+ * device passed as argument looking for a batman-adv soft interface.
156145 *
157146 * Return: true if the device is descendant of a batman-adv mesh interface (or
158147 * if it is a batman-adv interface itself), false otherwise
....@@ -162,22 +151,25 @@
162151 struct net *net = dev_net(net_dev);
163152 struct net_device *parent_dev;
164153 struct net *parent_net;
154
+ int iflink;
165155 bool ret;
166156
167157 /* check if this is a batman-adv mesh interface */
168158 if (batadv_softif_is_valid(net_dev))
169159 return true;
170160
171
- /* no more parents..stop recursion */
172
- if (dev_get_iflink(net_dev) == 0 ||
173
- dev_get_iflink(net_dev) == net_dev->ifindex)
161
+ iflink = dev_get_iflink(net_dev);
162
+ if (iflink == 0)
174163 return false;
175164
176165 parent_net = batadv_getlink_net(net_dev, net);
177166
167
+ /* iflink to itself, most likely physical device */
168
+ if (net == parent_net && iflink == net_dev->ifindex)
169
+ return false;
170
+
178171 /* recurse over the parent device */
179
- parent_dev = __dev_get_by_index((struct net *)parent_net,
180
- dev_get_iflink(net_dev));
172
+ parent_dev = __dev_get_by_index((struct net *)parent_net, iflink);
181173 /* if we got a NULL parent_dev there is something broken.. */
182174 if (!parent_dev) {
183175 pr_err("Cannot find parent device\n");
....@@ -227,14 +219,15 @@
227219 struct net_device *real_netdev = NULL;
228220 struct net *real_net;
229221 struct net *net;
230
- int ifindex;
222
+ int iflink;
231223
232224 ASSERT_RTNL();
233225
234226 if (!netdev)
235227 return NULL;
236228
237
- if (netdev->ifindex == dev_get_iflink(netdev)) {
229
+ iflink = dev_get_iflink(netdev);
230
+ if (iflink == 0) {
238231 dev_hold(netdev);
239232 return netdev;
240233 }
....@@ -244,9 +237,16 @@
244237 goto out;
245238
246239 net = dev_net(hard_iface->soft_iface);
247
- ifindex = dev_get_iflink(netdev);
248240 real_net = batadv_getlink_net(netdev, net);
249
- real_netdev = dev_get_by_index(real_net, ifindex);
241
+
242
+ /* iflink to itself, most likely physical device */
243
+ if (net == real_net && netdev->ifindex == iflink) {
244
+ real_netdev = netdev;
245
+ dev_hold(real_netdev);
246
+ goto out;
247
+ }
248
+
249
+ real_netdev = dev_get_by_index(real_net, iflink);
250250
251251 out:
252252 if (hard_iface)
....@@ -484,8 +484,8 @@
484484 if (new_hard_iface)
485485 kref_get(&new_hard_iface->refcount);
486486
487
- curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1);
488
- rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);
487
+ curr_hard_iface = rcu_replace_pointer(bat_priv->primary_if,
488
+ new_hard_iface, 1);
489489
490490 if (!new_hard_iface)
491491 goto out;
....@@ -613,7 +613,7 @@
613613 /* report to the other components the maximum amount of bytes that
614614 * batman-adv can send over the wire (without considering the payload
615615 * overhead). For example, this value is used by TT to compute the
616
- * maximum local table table size
616
+ * maximum local table size
617617 */
618618 atomic_set(&bat_priv->packet_size_max, min_mtu);
619619
....@@ -694,8 +694,8 @@
694694 * @slave: the interface enslaved in another master
695695 * @master: the master from which slave has to be removed
696696 *
697
- * Invoke ndo_del_slave on master passing slave as argument. In this way slave
698
- * is free'd and master can correctly change its internal state.
697
+ * Invoke ndo_del_slave on master passing slave as argument. In this way the
698
+ * slave is free'd and the master can correctly change its internal state.
699699 *
700700 * Return: 0 on success, a negative value representing the error otherwise
701701 */
....@@ -768,11 +768,6 @@
768768 hard_iface->soft_iface = soft_iface;
769769 bat_priv = netdev_priv(hard_iface->soft_iface);
770770
771
- if (bat_priv->num_ifaces >= UINT_MAX) {
772
- ret = -ENOSPC;
773
- goto err_dev;
774
- }
775
-
776771 ret = netdev_master_upper_dev_link(hard_iface->net_dev,
777772 soft_iface, NULL, NULL, NULL);
778773 if (ret)
....@@ -782,16 +777,7 @@
782777 if (ret < 0)
783778 goto err_upper;
784779
785
- hard_iface->if_num = bat_priv->num_ifaces;
786
- bat_priv->num_ifaces++;
787780 hard_iface->if_status = BATADV_IF_INACTIVE;
788
- ret = batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces);
789
- if (ret < 0) {
790
- bat_priv->algo_ops->iface.disable(hard_iface);
791
- bat_priv->num_ifaces--;
792
- hard_iface->if_status = BATADV_IF_NOT_IN_USE;
793
- goto err_upper;
794
- }
795781
796782 kref_get(&hard_iface->refcount);
797783 hard_iface->batman_adv_ptype.type = ethertype;
....@@ -842,6 +828,33 @@
842828 }
843829
844830 /**
831
+ * batadv_hardif_cnt() - get number of interfaces enslaved to soft interface
832
+ * @soft_iface: soft interface to check
833
+ *
834
+ * This function is only using RCU for locking - the result can therefore be
835
+ * off when another function is modifying the list at the same time. The
836
+ * caller can use the rtnl_lock to make sure that the count is accurate.
837
+ *
838
+ * Return: number of connected/enslaved hard interfaces
839
+ */
840
+static size_t batadv_hardif_cnt(const struct net_device *soft_iface)
841
+{
842
+ struct batadv_hard_iface *hard_iface;
843
+ size_t count = 0;
844
+
845
+ rcu_read_lock();
846
+ list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
847
+ if (hard_iface->soft_iface != soft_iface)
848
+ continue;
849
+
850
+ count++;
851
+ }
852
+ rcu_read_unlock();
853
+
854
+ return count;
855
+}
856
+
857
+/**
845858 * batadv_hardif_disable_interface() - Remove hard interface from soft interface
846859 * @hard_iface: hard interface to be removed
847860 * @autodel: whether to delete soft interface when it doesn't contain any other
....@@ -862,9 +875,6 @@
862875 hard_iface->net_dev->name);
863876 dev_remove_pack(&hard_iface->batman_adv_ptype);
864877 batadv_hardif_put(hard_iface);
865
-
866
- bat_priv->num_ifaces--;
867
- batadv_orig_hash_del_if(hard_iface, bat_priv->num_ifaces);
868878
869879 primary_if = batadv_primary_if_get_selected(bat_priv);
870880 if (hard_iface == primary_if) {
....@@ -889,7 +899,7 @@
889899 batadv_hardif_recalc_extra_skbroom(hard_iface->soft_iface);
890900
891901 /* nobody uses this interface anymore */
892
- if (bat_priv->num_ifaces == 0) {
902
+ if (batadv_hardif_cnt(hard_iface->soft_iface) <= 1) {
893903 batadv_gw_check_client_stop(bat_priv);
894904
895905 if (autodel == BATADV_IF_CLEANUP_AUTO)
....@@ -925,14 +935,11 @@
925935 if (ret)
926936 goto free_if;
927937
928
- hard_iface->if_num = 0;
929938 hard_iface->net_dev = net_dev;
930939 hard_iface->soft_iface = NULL;
931940 hard_iface->if_status = BATADV_IF_NOT_IN_USE;
932941
933
- ret = batadv_debugfs_add_hardif(hard_iface);
934
- if (ret)
935
- goto free_sysfs;
942
+ batadv_debugfs_add_hardif(hard_iface);
936943
937944 INIT_LIST_HEAD(&hard_iface->list);
938945 INIT_HLIST_HEAD(&hard_iface->neigh_list);
....@@ -946,16 +953,17 @@
946953 if (batadv_is_wifi_hardif(hard_iface))
947954 hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
948955
956
+ atomic_set(&hard_iface->hop_penalty, 0);
957
+
949958 batadv_v_hardif_init(hard_iface);
950959
951960 batadv_check_known_mac_addr(hard_iface->net_dev);
952961 kref_get(&hard_iface->refcount);
953962 list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
963
+ batadv_hardif_generation++;
954964
955965 return hard_iface;
956966
957
-free_sysfs:
958
- batadv_sysfs_del_hardif(&hard_iface->hardif_obj);
959967 free_if:
960968 kfree(hard_iface);
961969 release_dev:
....@@ -980,22 +988,6 @@
980988 batadv_debugfs_del_hardif(hard_iface);
981989 batadv_sysfs_del_hardif(&hard_iface->hardif_obj);
982990 batadv_hardif_put(hard_iface);
983
-}
984
-
985
-/**
986
- * batadv_hardif_remove_interfaces() - Remove all hard interfaces
987
- */
988
-void batadv_hardif_remove_interfaces(void)
989
-{
990
- struct batadv_hard_iface *hard_iface, *hard_iface_tmp;
991
-
992
- rtnl_lock();
993
- list_for_each_entry_safe(hard_iface, hard_iface_tmp,
994
- &batadv_hardif_list, list) {
995
- list_del_rcu(&hard_iface->list);
996
- batadv_hardif_remove_interface(hard_iface);
997
- }
998
- rtnl_unlock();
999991 }
1000992
1001993 /**
....@@ -1054,6 +1046,7 @@
10541046 case NETDEV_UNREGISTER:
10551047 case NETDEV_PRE_TYPE_CHANGE:
10561048 list_del_rcu(&hard_iface->list);
1049
+ batadv_hardif_generation++;
10571050
10581051 batadv_hardif_remove_interface(hard_iface);
10591052 break;