Merge tag 'batadv-next-pullrequest-20260930' of https://git.open-mesh.org/batadv

Simon Wunderlich says:

====================
This feature/cleanup patchset includes the following patches:

 - bla: avoid double free after failed backbone_hash alloc,
   by Sven Eckelmann

 - tt: update kerneldoc, by Sven Eckelmann (3 patches)

 - tt: fix local DEL handling, by Sven Eckelmann (3 patches)

 - tt: reject VLAN/TT entries before reaching size limit,
   by Sven Eckelmann

 - use assign_bit() where applicable, by Peng Fan

* tag 'batadv-next-pullrequest-20260930' of https://git.open-mesh.org/batadv:
  batman-adv: use assign_bit() where applicable
  batman-adv: tt: reject VLAN/TT entries before reaching size limit
  batman-adv: tt: queue local DEL event before marking entry as pending
  batman-adv: tt: queue local DEL event under bucket lock
  batman-adv: tt: only queue local del event after successful unlink
  batman-adv: tt: soften kernel-doc for batadv_tt_local_remove_now()
  batman-adv: tt: clarify responsibility for roam flag during removal
  batman-adv: tt: clarify kernel-doc for batadv_tt_global_purge_local
  batman-adv: bla: avoid double free after failed backbone_hash alloc
====================

Link: https://patch.msgid.link/20260930094558.3723766-1-sw@simonwunderlich.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski committed 2026-10-05 17:43:09 -07:00
commit 7770df9c56
7 files changed
+299 -98

No files matched your search

+1
View File
@@ -1625,6 +1625,7 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
bat_priv->bla.backbone_hash = batadv_hash_new(32);
if (!bat_priv->bla.backbone_hash) {
batadv_hash_destroy(bat_priv->bla.claim_hash);
bat_priv->bla.claim_hash = NULL;
return -ENOMEM;
}
+2 -4
View File
@@ -863,10 +863,8 @@ static void batadv_dat_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
u8 flags,
void *tvlv_value, u16 tvlv_value_len)
{
if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND)
clear_bit(BATADV_ORIG_CAPA_HAS_DAT, &orig->capabilities);
else
set_bit(BATADV_ORIG_CAPA_HAS_DAT, &orig->capabilities);
assign_bit(BATADV_ORIG_CAPA_HAS_DAT, &orig->capabilities,
!(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND));
}
/**
+1
View File
@@ -198,6 +198,7 @@ int batadv_mesh_init(struct net_device *mesh_iface)
spin_lock_init(&bat_priv->tt.roam_list_lock);
spin_lock_init(&bat_priv->tt.last_changeset_lock);
spin_lock_init(&bat_priv->tt.commit_lock);
spin_lock_init(&bat_priv->tt.reserve_lock);
spin_lock_init(&bat_priv->gw.list_lock);
#ifdef CONFIG_BATMAN_ADV_MCAST
spin_lock_init(&bat_priv->mcast.mla_lock);
+8
View File
@@ -561,6 +561,8 @@ void batadv_meshif_vlan_release(struct kref *ref)
hlist_del_rcu(&vlan->list);
spin_unlock_bh(&vlan->bat_priv->meshif_vlan_list_lock);
batadv_tt_local_unreserve_vlan(vlan->bat_priv);
kfree_rcu(vlan, rcu);
}
@@ -614,9 +616,15 @@ int batadv_meshif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
return -EEXIST;
}
if (!batadv_tt_local_reserve_vlan(bat_priv, vid)) {
spin_unlock_bh(&bat_priv->meshif_vlan_list_lock);
return -EMSGSIZE;
}
vlan = kzalloc_obj(*vlan, GFP_ATOMIC);
if (!vlan) {
spin_unlock_bh(&bat_priv->meshif_vlan_list_lock);
batadv_tt_local_unreserve_vlan(bat_priv);
return -ENOMEM;
}
+265 -94
View File
@@ -234,6 +234,162 @@ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
return tt_global_entry;
}
/**
* batadv_tt_len() - compute length in bytes of given number of tt changes
* @changes_num: number of tt changes
*
* Return: computed length in bytes.
*/
static int batadv_tt_len(int changes_num)
{
return changes_num * sizeof(struct batadv_tvlv_tt_change);
}
/**
* batadv_tt_local_transmit_size() - calculate the size of a full table response
* for a given number of VLANs and local TT entries
* @num_vlan: number of announced VLANs
* @num_entries: number of announced local TT entries
*
* Return: local translation table size in bytes.
*/
static int batadv_tt_local_transmit_size(u16 num_vlan, u16 num_entries)
{
int hdr_size;
/* header size of tvlv encapsulated tt response payload */
hdr_size = sizeof(struct batadv_unicast_tvlv_packet);
hdr_size += sizeof(struct batadv_tvlv_hdr);
hdr_size += sizeof(struct batadv_tvlv_tt_data);
hdr_size += num_vlan * sizeof(struct batadv_tvlv_tt_vlan_data);
return hdr_size + batadv_tt_len(num_entries);
}
/**
* batadv_tt_local_reserve() - reserve room in the transmittable local table
* @bat_priv: the bat priv with all the mesh interface information
* @num_vlan: number of VLANs to reserve
* @num_entries: number of local TT entries to reserve
* @table_size: stores the resulting worst case table size in bytes
*
* Add the requested number of VLANs and local TT entries to the reservation
* counters and check whether the local translation table would then still fit
* in a single full table response. The reservation is dropped again when it
* would not.
*
* The reservation has to happen before the related object is allocated. This
* way two parallel allocations cannot both observe enough room for themselves
* and end up with a local table which can no longer be transmitted.
*
* A granted reservation must be returned via batadv_tt_local_unreserve() when
* the related object is released or was never created.
*
* Return: true when the reservation was granted, false otherwise.
*/
static bool batadv_tt_local_reserve(struct batadv_priv *bat_priv, u16 num_vlan,
u16 num_entries, int *table_size)
{
int packet_size_max = READ_ONCE(bat_priv->packet_size_max);
scoped_guard(spinlock_bh, &bat_priv->tt.reserve_lock) {
bat_priv->tt.reserved_vlans += num_vlan;
bat_priv->tt.reserved_entries += num_entries;
*table_size = batadv_tt_local_transmit_size(bat_priv->tt.reserved_vlans,
bat_priv->tt.reserved_entries);
if (*table_size <= packet_size_max)
return true;
bat_priv->tt.reserved_vlans -= num_vlan;
bat_priv->tt.reserved_entries -= num_entries;
}
return false;
}
/**
* batadv_tt_local_unreserve() - return room in the transmittable local table
* @bat_priv: the bat priv with all the mesh interface information
* @num_vlan: number of VLANs to return
* @num_entries: number of local TT entries to return
*/
static void batadv_tt_local_unreserve(struct batadv_priv *bat_priv,
u16 num_vlan, u16 num_entries)
{
scoped_guard(spinlock_bh, &bat_priv->tt.reserve_lock) {
bat_priv->tt.reserved_vlans -= num_vlan;
bat_priv->tt.reserved_entries -= num_entries;
}
}
/**
* batadv_tt_local_reserve_entry() - reserve room for a new local TT entry
* @bat_priv: the bat priv with all the mesh interface information
* @addr: the mac address of the client to add
*
* Return: true when the reservation was granted, false otherwise.
*/
static bool batadv_tt_local_reserve_entry(struct batadv_priv *bat_priv,
const u8 *addr)
{
int table_size;
if (batadv_tt_local_reserve(bat_priv, 0, 1, &table_size))
return true;
net_ratelimited_function(batadv_info, bat_priv->mesh_iface,
"Local translation table size (%i) exceeds maximum packet size (%i); Ignoring new local tt entry: %pM\n",
table_size,
READ_ONCE(bat_priv->packet_size_max), addr);
return false;
}
/**
* batadv_tt_local_unreserve_entry() - return the room of a local TT entry
* @bat_priv: the bat priv with all the mesh interface information
*/
static void batadv_tt_local_unreserve_entry(struct batadv_priv *bat_priv)
{
batadv_tt_local_unreserve(bat_priv, 0, 1);
}
/**
* batadv_tt_local_reserve_vlan() - reserve room for a new VLAN
* @bat_priv: the bat priv with all the mesh interface information
* @vid: the VLAN identifier
*
* Each VLAN adds a per VLAN header to the full table response and therefore
* has to be reserved before batadv_meshif_create_vlan() allocates it.
*
* Return: true when the reservation was granted, false otherwise.
*/
bool batadv_tt_local_reserve_vlan(struct batadv_priv *bat_priv,
unsigned short vid)
{
int table_size;
if (batadv_tt_local_reserve(bat_priv, 1, 0, &table_size))
return true;
net_ratelimited_function(batadv_info, bat_priv->mesh_iface,
"Local translation table size (%i) exceeds maximum packet size (%i); Ignoring new VLAN: %d\n",
table_size, READ_ONCE(bat_priv->packet_size_max),
batadv_print_vid(vid));
return false;
}
/**
* batadv_tt_local_unreserve_vlan() - return the room of a VLAN
* @bat_priv: the bat priv with all the mesh interface information
*/
void batadv_tt_local_unreserve_vlan(struct batadv_priv *bat_priv)
{
batadv_tt_local_unreserve(bat_priv, 1, 0);
}
/**
* batadv_tt_local_entry_release() - release tt_local_entry from lists and queue
* for free after rcu grace period
@@ -246,6 +402,7 @@ static void batadv_tt_local_entry_release(struct kref *ref)
tt_local_entry = container_of(ref, struct batadv_tt_local_entry,
common.refcount);
batadv_tt_local_unreserve_entry(tt_local_entry->vlan->bat_priv);
batadv_meshif_vlan_put(tt_local_entry->vlan);
kfree_rcu(tt_local_entry, common.rcu);
@@ -461,23 +618,21 @@ static u16 batadv_tt_flags_get(struct batadv_tt_common_entry *common)
}
/**
* batadv_tt_local_event() - store a local TT event (ADD/DEL)
* __batadv_tt_local_event() - store a local TT event (ADD/DEL) with given flags
* @bat_priv: the bat priv with all the mesh interface information
* @tt_local_entry: the TT entry involved in the event
* @event_flags: flags to store in the event structure
* @common: the TT entry involved in the event
* @flags: flags of the TT entry combined with the event flags
*/
static void batadv_tt_local_event(struct batadv_priv *bat_priv,
struct batadv_tt_local_entry *tt_local_entry,
u8 event_flags)
static void __batadv_tt_local_event(struct batadv_priv *bat_priv,
const struct batadv_tt_common_entry *common,
u8 flags)
{
struct batadv_tt_common_entry *common = &tt_local_entry->common;
struct batadv_tt_change_node *tt_change_node;
struct batadv_tt_change_node *entry;
struct batadv_tt_change_node *safe;
bool del_op_requested;
bool del_op_entry;
size_t changes;
u8 flags;
tt_change_node = kmem_cache_alloc(batadv_tt_change_cache, GFP_ATOMIC);
if (!tt_change_node)
@@ -488,8 +643,6 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
ether_addr_copy(tt_change_node->change.addr, common->addr);
tt_change_node->change.vid = htons(common->vid);
flags = batadv_tt_flags_get(common) | event_flags;
tt_change_node->change.flags = flags;
del_op_requested = flags & BATADV_TT_CLIENT_DEL;
@@ -538,14 +691,20 @@ update_changes:
}
/**
* batadv_tt_len() - compute length in bytes of given number of tt changes
* @changes_num: number of tt changes
*
* Return: computed length in bytes.
* batadv_tt_local_event() - store a local TT event (ADD/DEL)
* @bat_priv: the bat priv with all the mesh interface information
* @tt_local_entry: the TT entry involved in the event
* @event_flags: flags to store in the event structure
*/
static int batadv_tt_len(int changes_num)
static void batadv_tt_local_event(struct batadv_priv *bat_priv,
struct batadv_tt_local_entry *tt_local_entry,
u8 event_flags)
{
return changes_num * sizeof(struct batadv_tvlv_tt_change);
struct batadv_tt_common_entry *common = &tt_local_entry->common;
u8 flags;
flags = batadv_tt_flags_get(common) | event_flags;
__batadv_tt_local_event(bat_priv, common, flags);
}
/**
@@ -571,7 +730,6 @@ static int batadv_tt_local_table_transmit_size(struct batadv_priv *bat_priv)
struct batadv_meshif_vlan *vlan;
u16 tt_local_entries = 0;
u16 num_vlan = 0;
int hdr_size;
rcu_read_lock();
hlist_for_each_entry_rcu(vlan, &bat_priv->meshif_vlan_list, list) {
@@ -580,13 +738,7 @@ static int batadv_tt_local_table_transmit_size(struct batadv_priv *bat_priv)
}
rcu_read_unlock();
/* header size of tvlv encapsulated tt response payload */
hdr_size = sizeof(struct batadv_unicast_tvlv_packet);
hdr_size += sizeof(struct batadv_tvlv_hdr);
hdr_size += sizeof(struct batadv_tvlv_tt_data);
hdr_size += num_vlan * sizeof(struct batadv_tvlv_tt_vlan_data);
return hdr_size + batadv_tt_len(tt_local_entries);
return batadv_tt_local_transmit_size(num_vlan, tt_local_entries);
}
/**
@@ -790,23 +942,15 @@ batadv_tt_local_create(struct net_device *mesh_iface, const u8 *addr,
struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
struct batadv_tt_local_entry *tt_local;
struct batadv_meshif_vlan *vlan;
int packet_size_max;
int table_size;
/* Ignore the client if we cannot send it in a full table response. */
table_size = batadv_tt_local_table_transmit_size(bat_priv);
table_size += batadv_tt_len(1);
packet_size_max = READ_ONCE(bat_priv->packet_size_max);
if (table_size > packet_size_max) {
net_ratelimited_function(batadv_info, mesh_iface,
"Local translation table size (%i) exceeds maximum packet size (%i); Ignoring new local tt entry: %pM\n",
table_size, packet_size_max, addr);
if (!batadv_tt_local_reserve_entry(bat_priv, addr))
return NULL;
}
tt_local = kmem_cache_alloc(batadv_tl_cache, GFP_ATOMIC);
if (!tt_local)
if (!tt_local) {
batadv_tt_local_unreserve_entry(bat_priv);
return NULL;
}
/* increase the refcounter of the related vlan */
vlan = batadv_meshif_vlan_get(bat_priv, vid);
@@ -815,6 +959,7 @@ batadv_tt_local_create(struct net_device *mesh_iface, const u8 *addr,
"adding TT local entry %pM to non-existent VLAN %d\n",
addr, batadv_print_vid(vid));
kmem_cache_free(batadv_tl_cache, tt_local);
batadv_tt_local_unreserve_entry(bat_priv);
return NULL;
}
@@ -1420,21 +1565,37 @@ int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
}
/**
* batadv_tt_local_set_pending_event() - trigger events for TT pending removal
* batadv_tt_local_set_pending() - mark local TT entry as pending removal
* @bat_priv: the bat priv with all the mesh interface information
* @tt_local_entry: local TT entry which was marked as BATADV_TT_CLIENT_PENDING
* @tt_local_entry: local TT entry to mark as BATADV_TT_CLIENT_PENDING
* @flags: TT change flags to announce together with the pending removal
* @message: debug message describing the reason for the change
*
* Schedule the TT change announcement for the entry. The caller must already
* have added BATADV_TT_CLIENT_PENDING to the @tt_local_entry
* Schedule the TT change announcement and set BATADV_TT_CLIENT_PENDING on the
* entry. The entry is kept in the local table until the next TTVN increment
* so that a consistency-check response can still be answered.
*
* Next to the flags_lock of the entry, the caller must hold the hash bucket
* list_lock of @tt_local_entry. Otherwise
* batadv_tt_local_purge_pending_clients() could remove the entry before its
* change was queued.
*/
static void
batadv_tt_local_set_pending_event(struct batadv_priv *bat_priv,
struct batadv_tt_local_entry *tt_local_entry,
u16 flags, const char *message)
batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
struct batadv_tt_local_entry *tt_local_entry,
u16 flags, const char *message)
__must_hold(&tt_local_entry->common.flags_lock)
{
batadv_tt_local_event(bat_priv, tt_local_entry, flags);
struct batadv_tt_common_entry *common = &tt_local_entry->common;
struct batadv_hashtable *hash = bat_priv->tt.local_hash;
u32 i;
i = batadv_choose_tt(common, hash->size);
lockdep_assert_held(&hash->list_locks[i]);
lockdep_assert_held(&common->flags_lock);
__batadv_tt_local_event(bat_priv, common, common->flags | flags);
common->flags |= BATADV_TT_CLIENT_PENDING;
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Local tt entry (%pM, vid: %d) pending to be removed: %s\n",
@@ -1443,45 +1604,77 @@ batadv_tt_local_set_pending_event(struct batadv_priv *bat_priv,
}
/**
* batadv_tt_local_mark_removed() - mark a local entry as removed
* batadv_tt_local_mark_removed() - mark a local entry as removed and queue DEL
* @bat_priv: the bat priv with all the mesh interface information
* @tt_local_entry: local TT entry to mark
* @message: message to append to the log on deletion
* @roaming: true if the deletion is due to a roaming event
* @curr_flags: pointer to store the flags of the entry before it was marked
*
* An already announced entry is marked as BATADV_TT_CLIENT_PENDING and the
* (roamed) DEL change is queued. Both happen under the hash bucket list_lock
* of the entry to prevent concurrent batadv_tt_local_purge_pending_clients()
* from removing the entry and batadv_tt_local_transition_new() from clearing
* BATADV_TT_CLIENT_NEW after it was checked.
*
* Return: true if the entry has to be kept in the local table until the next
* ttvn increment, false if it can be purged immediately.
*/
static bool
batadv_tt_local_mark_removed(struct batadv_tt_local_entry *tt_local_entry,
bool roaming, u16 *curr_flags)
batadv_tt_local_mark_removed(struct batadv_priv *bat_priv,
struct batadv_tt_local_entry *tt_local_entry,
const char *message, bool roaming, u16 *curr_flags)
{
spinlock_t *list_lock; /* protects write access to the hash lists */
struct batadv_tt_common_entry *common = &tt_local_entry->common;
struct batadv_hashtable *hash = bat_priv->tt.local_hash;
bool pending = false;
u16 flags;
u32 i;
i = batadv_choose_tt(common, hash->size);
list_lock = &hash->list_locks[i];
spin_lock_bh(list_lock);
scoped_guard(spinlock_bh, &common->flags_lock) {
*curr_flags = common->flags;
/* mark the local client as ROAMed */
/* if this global entry addition is due to a roaming, the node
* has to mark the local entry as "roamed" in order to
* correctly reroute packets later
*/
if (roaming)
common->flags |= BATADV_TT_CLIENT_ROAM;
if (!(common->flags & BATADV_TT_CLIENT_NEW)) {
common->flags |= BATADV_TT_CLIENT_PENDING;
pending = true;
}
if (common->flags & BATADV_TT_CLIENT_NEW)
break;
flags = BATADV_TT_CLIENT_DEL;
if (roaming)
flags |= BATADV_TT_CLIENT_ROAM;
batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
message);
pending = true;
}
spin_unlock_bh(list_lock);
return pending;
}
/**
* batadv_tt_local_remove_now() - purge a local entry which was never announced
* batadv_tt_local_remove_now() - purge a local entry which was not (yet) announced
* @bat_priv: the bat priv with all the mesh interface information
* @tt_local_entry: local TT entry to purge
*
* A client which was added right after the last ttvn increment was never sent
* to the other nodes. It can therefore be dropped from the local table without
* waiting for the next ttvn increment.
* A client which was added right after the last ttvn increment was not (yet)
* sent to the other nodes. It can therefore be dropped from the local table
* without waiting for the next ttvn increment.
*
* If it was still announced by a parallel context before it was removed from
* the hash, then the local TT size adjustment will be handled automatically.
*/
static void
batadv_tt_local_remove_now(struct batadv_priv *bat_priv,
@@ -1490,8 +1683,6 @@ batadv_tt_local_remove_now(struct batadv_priv *bat_priv,
struct batadv_tt_common_entry *common = &tt_local_entry->common;
struct hlist_node *tt_removed_node;
batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
/* remove exactly this object when still present in hash */
tt_removed_node = batadv_hash_remove(bat_priv->tt.local_hash,
batadv_compare_tt_entry,
@@ -1499,6 +1690,8 @@ batadv_tt_local_remove_now(struct batadv_priv *bat_priv,
if (!tt_removed_node)
return;
batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
/* batadv_tt_local_transition_new() may have committed the entry and
* thus counted it in the local table size since the
* BATADV_TT_CLIENT_NEW check in batadv_tt_local_mark_removed().
@@ -1526,27 +1719,16 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
{
struct batadv_tt_local_entry *tt_local_entry;
u16 curr_flags;
u16 flags;
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
if (!tt_local_entry)
return BATADV_NO_FLAGS;
flags = BATADV_TT_CLIENT_DEL;
/* if this global entry addition is due to a roaming, the node has to
* mark the local entry as "roamed" in order to correctly reroute
* packets later
/* if this client has been added right now, it is possible to
* immediately purge it
*/
if (roaming)
flags |= BATADV_TT_CLIENT_ROAM;
if (batadv_tt_local_mark_removed(tt_local_entry, roaming, &curr_flags))
batadv_tt_local_set_pending_event(bat_priv, tt_local_entry,
flags, message);
else
/* if this client has been added right now, it is possible to
* immediately purge it
*/
if (!batadv_tt_local_mark_removed(bat_priv, tt_local_entry, message,
roaming, &curr_flags))
batadv_tt_local_remove_now(bat_priv, tt_local_entry);
batadv_tt_local_entry_put(tt_local_entry);
@@ -1571,37 +1753,25 @@ static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
hlist_for_each_entry_safe(tt_common_entry, node_tmp, head,
hash_entry) {
bool cont = false;
tt_local_entry = container_of(tt_common_entry,
struct batadv_tt_local_entry,
common);
scoped_guard(spinlock_bh, &tt_local_entry->common.flags_lock) {
if (tt_local_entry->common.flags & BATADV_TT_CLIENT_NOPURGE) {
cont = true;
if (tt_local_entry->common.flags & BATADV_TT_CLIENT_NOPURGE)
break;
}
/* entry already marked for deletion */
if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) {
cont = true;
if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
break;
}
if (!batadv_has_timed_out(tt_local_entry->last_seen, timeout)) {
cont = true;
if (!batadv_has_timed_out(tt_local_entry->last_seen, timeout))
break;
}
tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING;
batadv_tt_local_set_pending(bat_priv, tt_local_entry,
BATADV_TT_CLIENT_DEL,
"timed out");
}
if (cont)
continue;
batadv_tt_local_set_pending_event(bat_priv, tt_local_entry,
BATADV_TT_CLIENT_DEL, "timed out");
}
}
@@ -1870,9 +2040,10 @@ out:
* @tt_global_entry: the global TT entry of the announced client
* @flags: TT flags announced for this non-mesh client
*
* A client which is announced by another originator is no longer a local
* client. Remove it from the local table and take over the WIFI flag it was
* tracked with.
* A non-multicast client which is announced by another originator is no longer
* a local client. Remove it from the local table and (for the global entry)
* take over the WIFI flag it was tracked with. Reset the roaming flag in case
* the announcement didn't contain the roaming flag.
*/
static void
batadv_tt_global_purge_local(struct batadv_priv *bat_priv,
+3
View File
@@ -16,6 +16,9 @@
#include <linux/types.h>
int batadv_tt_init(struct batadv_priv *bat_priv);
bool batadv_tt_local_reserve_vlan(struct batadv_priv *bat_priv,
unsigned short vid);
void batadv_tt_local_unreserve_vlan(struct batadv_priv *bat_priv);
bool batadv_tt_local_add(struct net_device *mesh_iface, const u8 *addr,
unsigned short vid, int ifindex, u32 mark);
u16 batadv_tt_local_remove(struct batadv_priv *bat_priv,
+19
View File
@@ -1055,6 +1055,25 @@ struct batadv_priv_tt {
*/
spinlock_t commit_lock;
/**
* @reserved_entries: number of local TT entries which are currently
* allocated or about to be allocated. Together with @reserved_vlans it
* describes the worst case size of a full table response.
*/
u16 reserved_entries;
/**
* @reserved_vlans: number of mesh interface VLANs which are currently
* allocated or about to be allocated. Together with @reserved_entries
* it describes the worst case size of a full table response.
*/
u16 reserved_vlans;
/**
* @reserve_lock: lock protecting @reserved_entries & @reserved_vlans
*/
spinlock_t reserve_lock;
/** @work: work queue callback item for translation table purging */
struct delayed_work work;
};