hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
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
....@@ -632,7 +632,19 @@
632632 */
633633 void batadv_update_min_mtu(struct net_device *soft_iface)
634634 {
635
- soft_iface->mtu = batadv_hardif_min_mtu(soft_iface);
635
+ struct batadv_priv *bat_priv = netdev_priv(soft_iface);
636
+ int limit_mtu;
637
+ int mtu;
638
+
639
+ mtu = batadv_hardif_min_mtu(soft_iface);
640
+
641
+ if (bat_priv->mtu_set_by_user)
642
+ limit_mtu = bat_priv->mtu_set_by_user;
643
+ else
644
+ limit_mtu = ETH_DATA_LEN;
645
+
646
+ mtu = min(mtu, limit_mtu);
647
+ dev_set_mtu(soft_iface, mtu);
636648
637649 /* Check if the local translate table should be cleaned up to match a
638650 * new (and smaller) MTU.
....@@ -694,8 +706,8 @@
694706 * @slave: the interface enslaved in another master
695707 * @master: the master from which slave has to be removed
696708 *
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.
709
+ * Invoke ndo_del_slave on master passing slave as argument. In this way the
710
+ * slave is free'd and the master can correctly change its internal state.
699711 *
700712 * Return: 0 on success, a negative value representing the error otherwise
701713 */
....@@ -768,11 +780,6 @@
768780 hard_iface->soft_iface = soft_iface;
769781 bat_priv = netdev_priv(hard_iface->soft_iface);
770782
771
- if (bat_priv->num_ifaces >= UINT_MAX) {
772
- ret = -ENOSPC;
773
- goto err_dev;
774
- }
775
-
776783 ret = netdev_master_upper_dev_link(hard_iface->net_dev,
777784 soft_iface, NULL, NULL, NULL);
778785 if (ret)
....@@ -782,16 +789,7 @@
782789 if (ret < 0)
783790 goto err_upper;
784791
785
- hard_iface->if_num = bat_priv->num_ifaces;
786
- bat_priv->num_ifaces++;
787792 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
- }
795793
796794 kref_get(&hard_iface->refcount);
797795 hard_iface->batman_adv_ptype.type = ethertype;
....@@ -842,6 +840,33 @@
842840 }
843841
844842 /**
843
+ * batadv_hardif_cnt() - get number of interfaces enslaved to soft interface
844
+ * @soft_iface: soft interface to check
845
+ *
846
+ * This function is only using RCU for locking - the result can therefore be
847
+ * off when another function is modifying the list at the same time. The
848
+ * caller can use the rtnl_lock to make sure that the count is accurate.
849
+ *
850
+ * Return: number of connected/enslaved hard interfaces
851
+ */
852
+static size_t batadv_hardif_cnt(const struct net_device *soft_iface)
853
+{
854
+ struct batadv_hard_iface *hard_iface;
855
+ size_t count = 0;
856
+
857
+ rcu_read_lock();
858
+ list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
859
+ if (hard_iface->soft_iface != soft_iface)
860
+ continue;
861
+
862
+ count++;
863
+ }
864
+ rcu_read_unlock();
865
+
866
+ return count;
867
+}
868
+
869
+/**
845870 * batadv_hardif_disable_interface() - Remove hard interface from soft interface
846871 * @hard_iface: hard interface to be removed
847872 * @autodel: whether to delete soft interface when it doesn't contain any other
....@@ -862,9 +887,6 @@
862887 hard_iface->net_dev->name);
863888 dev_remove_pack(&hard_iface->batman_adv_ptype);
864889 batadv_hardif_put(hard_iface);
865
-
866
- bat_priv->num_ifaces--;
867
- batadv_orig_hash_del_if(hard_iface, bat_priv->num_ifaces);
868890
869891 primary_if = batadv_primary_if_get_selected(bat_priv);
870892 if (hard_iface == primary_if) {
....@@ -889,7 +911,7 @@
889911 batadv_hardif_recalc_extra_skbroom(hard_iface->soft_iface);
890912
891913 /* nobody uses this interface anymore */
892
- if (bat_priv->num_ifaces == 0) {
914
+ if (batadv_hardif_cnt(hard_iface->soft_iface) <= 1) {
893915 batadv_gw_check_client_stop(bat_priv);
894916
895917 if (autodel == BATADV_IF_CLEANUP_AUTO)
....@@ -925,14 +947,11 @@
925947 if (ret)
926948 goto free_if;
927949
928
- hard_iface->if_num = 0;
929950 hard_iface->net_dev = net_dev;
930951 hard_iface->soft_iface = NULL;
931952 hard_iface->if_status = BATADV_IF_NOT_IN_USE;
932953
933
- ret = batadv_debugfs_add_hardif(hard_iface);
934
- if (ret)
935
- goto free_sysfs;
954
+ batadv_debugfs_add_hardif(hard_iface);
936955
937956 INIT_LIST_HEAD(&hard_iface->list);
938957 INIT_HLIST_HEAD(&hard_iface->neigh_list);
....@@ -946,16 +965,17 @@
946965 if (batadv_is_wifi_hardif(hard_iface))
947966 hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
948967
968
+ atomic_set(&hard_iface->hop_penalty, 0);
969
+
949970 batadv_v_hardif_init(hard_iface);
950971
951972 batadv_check_known_mac_addr(hard_iface->net_dev);
952973 kref_get(&hard_iface->refcount);
953974 list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
975
+ batadv_hardif_generation++;
954976
955977 return hard_iface;
956978
957
-free_sysfs:
958
- batadv_sysfs_del_hardif(&hard_iface->hardif_obj);
959979 free_if:
960980 kfree(hard_iface);
961981 release_dev:
....@@ -980,22 +1000,6 @@
9801000 batadv_debugfs_del_hardif(hard_iface);
9811001 batadv_sysfs_del_hardif(&hard_iface->hardif_obj);
9821002 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();
9991003 }
10001004
10011005 /**
....@@ -1054,6 +1058,7 @@
10541058 case NETDEV_UNREGISTER:
10551059 case NETDEV_PRE_TYPE_CHANGE:
10561060 list_del_rcu(&hard_iface->list);
1061
+ batadv_hardif_generation++;
10571062
10581063 batadv_hardif_remove_interface(hard_iface);
10591064 break;