The following commit has been merged in the batadv/net-next branch: commit 44ce3511c21c6ba87a719a0b9f140822cc1cc00b Merge: 2196ceea2d39018a85a037cbb4c22666edb5a72c f4c9c2cc827d803159730b1da813a0c595969831 Author: Paolo Abeni pabeni@redhat.com Date: Tue Feb 11 10:39:46 2025 +0100
Merge tag 'batadv-net-pullrequest-20250207' of git://git.open-mesh.org/linux-merge
Simon Wunderlich says:
==================== Here are some batman-adv bugfixes:
- Fix panic during interface removal in BATMAN V, by Andy Strohman
- Cleanup BATMAN V/ELP metric handling, by Sven Eckelmann (2 patches)
- Fix incorrect offset in batadv_tt_tvlv_ogm_handler_v1(), by Remi Pommarel
* tag 'batadv-net-pullrequest-20250207' of git://git.open-mesh.org/linux-merge: batman-adv: Fix incorrect offset in batadv_tt_tvlv_ogm_handler_v1() batman-adv: Drop unmanaged ELP metric worker batman-adv: Ignore neighbor throughput metrics in error case batman-adv: fix panic during interface removal ====================
Link: https://patch.msgid.link/20250207095823.26043-1-sw@simonwunderlich.de Signed-off-by: Paolo Abeni pabeni@redhat.com
diff --combined net/batman-adv/translation-table.c index 3c0a14a582e4b,7d5de4cbb814f..d4b71d34310f4 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@@ -15,7 -15,6 +15,7 @@@ #include <linux/compiler.h> #include <linux/container_of.h> #include <linux/crc32c.h> +#include <linux/err.h> #include <linux/errno.h> #include <linux/etherdevice.h> #include <linux/gfp.h> @@@ -40,6 -39,7 +40,6 @@@ #include <linux/workqueue.h> #include <net/genetlink.h> #include <net/netlink.h> -#include <net/sock.h> #include <uapi/linux/batadv_packet.h> #include <uapi/linux/batman_adv.h>
@@@ -423,8 -423,8 +423,8 @@@ static void batadv_tt_local_event(struc struct batadv_tt_change_node *tt_change_node, *entry, *safe; struct batadv_tt_common_entry *common = &tt_local_entry->common; u8 flags = common->flags | event_flags; - bool event_removed = false; bool del_op_requested, del_op_entry; + size_t changes;
tt_change_node = kmem_cache_alloc(batadv_tt_change_cache, GFP_ATOMIC); if (!tt_change_node) @@@ -438,45 -438,51 +438,45 @@@
del_op_requested = flags & BATADV_TT_CLIENT_DEL;
- /* check for ADD+DEL or DEL+ADD events */ + /* check for ADD+DEL, DEL+ADD, ADD+ADD or DEL+DEL events */ spin_lock_bh(&bat_priv->tt.changes_list_lock); + changes = READ_ONCE(bat_priv->tt.local_changes); list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, list) { if (!batadv_compare_eth(entry->change.addr, common->addr)) continue;
- /* DEL+ADD in the same orig interval have no effect and can be - * removed to avoid silly behaviour on the receiver side. The - * other way around (ADD+DEL) can happen in case of roaming of - * a client still in the NEW state. Roaming of NEW clients is - * now possible due to automatically recognition of "temporary" - * clients - */ del_op_entry = entry->change.flags & BATADV_TT_CLIENT_DEL; - if (!del_op_requested && del_op_entry) - goto del; - if (del_op_requested && !del_op_entry) - goto del; - - /* this is a second add in the same originator interval. It - * means that flags have been changed: update them! - */ - if (!del_op_requested && !del_op_entry) + if (del_op_requested != del_op_entry) { + /* DEL+ADD in the same orig interval have no effect and + * can be removed to avoid silly behaviour on the + * receiver side. The other way around (ADD+DEL) can + * happen in case of roaming of a client still in the + * NEW state. Roaming of NEW clients is now possible due + * to automatically recognition of "temporary" clients + */ + list_del(&entry->list); + kmem_cache_free(batadv_tt_change_cache, entry); + changes--; + } else { + /* this is a second add or del in the same originator + * interval. It could mean that flags have been changed + * (e.g. double add): update them + */ entry->change.flags = flags; + }
- continue; -del: - list_del(&entry->list); - kmem_cache_free(batadv_tt_change_cache, entry); kmem_cache_free(batadv_tt_change_cache, tt_change_node); - event_removed = true; - goto unlock; + goto update_changes; }
/* track the change in the OGMinterval list */ list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list); + changes++;
-unlock: +update_changes: + WRITE_ONCE(bat_priv->tt.local_changes, changes); spin_unlock_bh(&bat_priv->tt.changes_list_lock); - - if (event_removed) - atomic_dec(&bat_priv->tt.local_changes); - else - atomic_inc(&bat_priv->tt.local_changes); }
/** @@@ -946,7 -952,7 +946,7 @@@ static void batadv_tt_tvlv_container_up size_t tt_extra_len = 0; u16 tvlv_len;
- tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes); + tt_diff_entries_num = READ_ONCE(bat_priv->tt.local_changes); tt_diff_len = batadv_tt_len(tt_diff_entries_num);
/* if we have too many changes for one packet don't send any @@@ -973,7 -979,7 +973,7 @@@ goto container_register;
spin_lock_bh(&bat_priv->tt.changes_list_lock); - atomic_set(&bat_priv->tt.local_changes, 0); + WRITE_ONCE(bat_priv->tt.local_changes, 0);
list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, list) { @@@ -1130,18 -1136,26 +1130,18 @@@ batadv_tt_local_dump_bucket(struct sk_b */ int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb) { - struct net *net = sock_net(cb->skb->sk); struct net_device *soft_iface; struct batadv_priv *bat_priv; struct batadv_hard_iface *primary_if = NULL; struct batadv_hashtable *hash; int ret; - int ifindex; int bucket = cb->args[0]; int idx = cb->args[1]; int portid = NETLINK_CB(cb->skb).portid;
- ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX); - if (!ifindex) - return -EINVAL; - - soft_iface = dev_get_by_index(net, ifindex); - if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { - ret = -ENODEV; - goto out; - } + soft_iface = batadv_netlink_get_softif(cb); + if (IS_ERR(soft_iface)) + return PTR_ERR(soft_iface);
bat_priv = netdev_priv(soft_iface);
@@@ -1381,7 -1395,7 +1381,7 @@@ static void batadv_tt_changes_list_free kmem_cache_free(batadv_tt_change_cache, entry); }
- atomic_set(&bat_priv->tt.local_changes, 0); + WRITE_ONCE(bat_priv->tt.local_changes, 0); spin_unlock_bh(&bat_priv->tt.changes_list_lock); }
@@@ -1897,20 -1911,28 +1897,20 @@@ batadv_tt_global_dump_bucket(struct sk_ */ int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb) { - struct net *net = sock_net(cb->skb->sk); struct net_device *soft_iface; struct batadv_priv *bat_priv; struct batadv_hard_iface *primary_if = NULL; struct batadv_hashtable *hash; struct hlist_head *head; int ret; - int ifindex; int bucket = cb->args[0]; int idx = cb->args[1]; int sub = cb->args[2]; int portid = NETLINK_CB(cb->skb).portid;
- ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX); - if (!ifindex) - return -EINVAL; - - soft_iface = dev_get_by_index(net, ifindex); - if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { - ret = -ENODEV; - goto out; - } + soft_iface = batadv_netlink_get_softif(cb); + if (IS_ERR(soft_iface)) + return PTR_ERR(soft_iface);
bat_priv = netdev_priv(soft_iface);
@@@ -3634,7 -3656,7 +3634,7 @@@ static void batadv_tt_local_commit_chan { lockdep_assert_held(&bat_priv->tt.commit_lock);
- if (atomic_read(&bat_priv->tt.local_changes) < 1) { + if (READ_ONCE(bat_priv->tt.local_changes) == 0) { if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt)) batadv_tt_tvlv_container_update(bat_priv); return; @@@ -3937,23 -3959,21 +3937,21 @@@ static void batadv_tt_tvlv_ogm_handler_ struct batadv_tvlv_tt_change *tt_change; struct batadv_tvlv_tt_data *tt_data; u16 num_entries, num_vlan; - size_t flex_size; + size_t tt_data_sz;
if (tvlv_value_len < sizeof(*tt_data)) return;
tt_data = tvlv_value; - tvlv_value_len -= sizeof(*tt_data); - num_vlan = ntohs(tt_data->num_vlan);
- flex_size = flex_array_size(tt_data, vlan_data, num_vlan); - if (tvlv_value_len < flex_size) + tt_data_sz = struct_size(tt_data, vlan_data, num_vlan); + if (tvlv_value_len < tt_data_sz) return;
tt_change = (struct batadv_tvlv_tt_change *)((void *)tt_data - + flex_size); - tvlv_value_len -= flex_size; + + tt_data_sz); + tvlv_value_len -= tt_data_sz;
num_entries = batadv_tt_entries(tvlv_value_len);
diff --combined net/batman-adv/types.h index f491bff8c51b8,85a50096f5b24..fe89f08533fe6 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@@ -596,9 -596,6 +596,6 @@@ struct batadv_hardif_neigh_node_bat_v * neighbor */ unsigned long last_unicast_tx; - - /** @metric_work: work queue callback item for metric update */ - struct work_struct metric_work; };
/** @@@ -1022,7 -1019,7 +1019,7 @@@ struct batadv_priv_tt atomic_t ogm_append_cnt;
/** @local_changes: changes registered in an originator interval */ - atomic_t local_changes; + size_t local_changes;
/** * @changes_list: tracks tt local changes within an originator interval @@@ -1044,7 -1041,7 +1041,7 @@@ */ struct list_head roam_list;
- /** @changes_list_lock: lock protecting changes_list */ + /** @changes_list_lock: lock protecting changes_list & local_changes */ spinlock_t changes_list_lock;
/** @req_list_lock: lock protecting req_list */