Commit 4d2bbb0e authored by David S. Miller's avatar David S. Miller

Merge tag 'batadv-net-for-davem-20170802' of git://git.open-mesh.org/linux-merge

Simon Wunderlich says:

====================
Here is a batman-adv bugfix:

 - fix TT sync flag inconsistency problems, which can lead to excess packets,
   by Linus Luessing
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ed254971 54e22f26
...@@ -1549,9 +1549,41 @@ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, ...@@ -1549,9 +1549,41 @@ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
return found; return found;
} }
/**
* batadv_tt_global_sync_flags - update TT sync flags
* @tt_global: the TT global entry to update sync flags in
*
* Updates the sync flag bits in the tt_global flag attribute with a logical
* OR of all sync flags from any of its TT orig entries.
*/
static void
batadv_tt_global_sync_flags(struct batadv_tt_global_entry *tt_global)
{
struct batadv_tt_orig_list_entry *orig_entry;
const struct hlist_head *head;
u16 flags = BATADV_NO_FLAGS;
rcu_read_lock();
head = &tt_global->orig_list;
hlist_for_each_entry_rcu(orig_entry, head, list)
flags |= orig_entry->flags;
rcu_read_unlock();
flags |= tt_global->common.flags & (~BATADV_TT_SYNC_MASK);
tt_global->common.flags = flags;
}
/**
* batadv_tt_global_orig_entry_add - add or update a TT orig entry
* @tt_global: the TT global entry to add an orig entry in
* @orig_node: the originator to add an orig entry for
* @ttvn: translation table version number of this changeset
* @flags: TT sync flags
*/
static void static void
batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
struct batadv_orig_node *orig_node, int ttvn) struct batadv_orig_node *orig_node, int ttvn,
u8 flags)
{ {
struct batadv_tt_orig_list_entry *orig_entry; struct batadv_tt_orig_list_entry *orig_entry;
...@@ -1561,7 +1593,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, ...@@ -1561,7 +1593,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
* was added during a "temporary client detection" * was added during a "temporary client detection"
*/ */
orig_entry->ttvn = ttvn; orig_entry->ttvn = ttvn;
goto out; orig_entry->flags = flags;
goto sync_flags;
} }
orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC); orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC);
...@@ -1573,6 +1606,7 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, ...@@ -1573,6 +1606,7 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
batadv_tt_global_size_inc(orig_node, tt_global->common.vid); batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
orig_entry->orig_node = orig_node; orig_entry->orig_node = orig_node;
orig_entry->ttvn = ttvn; orig_entry->ttvn = ttvn;
orig_entry->flags = flags;
kref_init(&orig_entry->refcount); kref_init(&orig_entry->refcount);
spin_lock_bh(&tt_global->list_lock); spin_lock_bh(&tt_global->list_lock);
...@@ -1582,6 +1616,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, ...@@ -1582,6 +1616,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
spin_unlock_bh(&tt_global->list_lock); spin_unlock_bh(&tt_global->list_lock);
atomic_inc(&tt_global->orig_list_count); atomic_inc(&tt_global->orig_list_count);
sync_flags:
batadv_tt_global_sync_flags(tt_global);
out: out:
if (orig_entry) if (orig_entry)
batadv_tt_orig_list_entry_put(orig_entry); batadv_tt_orig_list_entry_put(orig_entry);
...@@ -1703,10 +1739,10 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, ...@@ -1703,10 +1739,10 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
} }
/* the change can carry possible "attribute" flags like the /* the change can carry possible "attribute" flags like the
* TT_CLIENT_WIFI, therefore they have to be copied in the * TT_CLIENT_TEMP, therefore they have to be copied in the
* client entry * client entry
*/ */
common->flags |= flags; common->flags |= flags & (~BATADV_TT_SYNC_MASK);
/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
* one originator left in the list and we previously received a * one originator left in the list and we previously received a
...@@ -1723,7 +1759,8 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, ...@@ -1723,7 +1759,8 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
} }
add_orig_entry: add_orig_entry:
/* add the new orig_entry (if needed) or update it */ /* add the new orig_entry (if needed) or update it */
batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn,
flags & BATADV_TT_SYNC_MASK);
batadv_dbg(BATADV_DBG_TT, bat_priv, batadv_dbg(BATADV_DBG_TT, bat_priv,
"Creating new global tt entry: %pM (vid: %d, via %pM)\n", "Creating new global tt entry: %pM (vid: %d, via %pM)\n",
...@@ -1946,6 +1983,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -1946,6 +1983,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
struct batadv_tt_orig_list_entry *orig, struct batadv_tt_orig_list_entry *orig,
bool best) bool best)
{ {
u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags;
void *hdr; void *hdr;
struct batadv_orig_node_vlan *vlan; struct batadv_orig_node_vlan *vlan;
u8 last_ttvn; u8 last_ttvn;
...@@ -1975,7 +2013,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -1975,7 +2013,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) || nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) ||
nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) || nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) || nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags)) nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, flags))
goto nla_put_failure; goto nla_put_failure;
if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST)) if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
...@@ -2589,6 +2627,7 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, ...@@ -2589,6 +2627,7 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv,
unsigned short vid) unsigned short vid)
{ {
struct batadv_hashtable *hash = bat_priv->tt.global_hash; struct batadv_hashtable *hash = bat_priv->tt.global_hash;
struct batadv_tt_orig_list_entry *tt_orig;
struct batadv_tt_common_entry *tt_common; struct batadv_tt_common_entry *tt_common;
struct batadv_tt_global_entry *tt_global; struct batadv_tt_global_entry *tt_global;
struct hlist_head *head; struct hlist_head *head;
...@@ -2627,8 +2666,9 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, ...@@ -2627,8 +2666,9 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv,
/* find out if this global entry is announced by this /* find out if this global entry is announced by this
* originator * originator
*/ */
if (!batadv_tt_global_entry_has_orig(tt_global, tt_orig = batadv_tt_global_orig_entry_find(tt_global,
orig_node)) orig_node);
if (!tt_orig)
continue; continue;
/* use network order to read the VID: this ensures that /* use network order to read the VID: this ensures that
...@@ -2640,10 +2680,12 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, ...@@ -2640,10 +2680,12 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv,
/* compute the CRC on flags that have to be kept in sync /* compute the CRC on flags that have to be kept in sync
* among nodes * among nodes
*/ */
flags = tt_common->flags & BATADV_TT_SYNC_MASK; flags = tt_orig->flags;
crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags)); crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN); crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
batadv_tt_orig_list_entry_put(tt_orig);
} }
rcu_read_unlock(); rcu_read_unlock();
} }
......
...@@ -1260,6 +1260,7 @@ struct batadv_tt_global_entry { ...@@ -1260,6 +1260,7 @@ struct batadv_tt_global_entry {
* struct batadv_tt_orig_list_entry - orig node announcing a non-mesh client * struct batadv_tt_orig_list_entry - orig node announcing a non-mesh client
* @orig_node: pointer to orig node announcing this non-mesh client * @orig_node: pointer to orig node announcing this non-mesh client
* @ttvn: translation table version number which added the non-mesh client * @ttvn: translation table version number which added the non-mesh client
* @flags: per orig entry TT sync flags
* @list: list node for batadv_tt_global_entry::orig_list * @list: list node for batadv_tt_global_entry::orig_list
* @refcount: number of contexts the object is used * @refcount: number of contexts the object is used
* @rcu: struct used for freeing in an RCU-safe manner * @rcu: struct used for freeing in an RCU-safe manner
...@@ -1267,6 +1268,7 @@ struct batadv_tt_global_entry { ...@@ -1267,6 +1268,7 @@ struct batadv_tt_global_entry {
struct batadv_tt_orig_list_entry { struct batadv_tt_orig_list_entry {
struct batadv_orig_node *orig_node; struct batadv_orig_node *orig_node;
u8 ttvn; u8 ttvn;
u8 flags;
struct hlist_node list; struct hlist_node list;
struct kref refcount; struct kref refcount;
struct rcu_head rcu; struct rcu_head rcu;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment