]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/batman-adv/translation-table.c
Merge tag 'char-misc-4.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregk...
[karo-tx-linux.git] / net / batman-adv / translation-table.c
index e1133bc634b5e8ed9a4639677e577a0d52e7c1d5..8a3ce79b1307b7f260ce2f64e96bdacfb9a322f0 100644 (file)
@@ -1549,9 +1549,41 @@ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
        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
 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;
 
@@ -1561,7 +1593,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
                 * was added during a "temporary client detection"
                 */
                orig_entry->ttvn = ttvn;
-               goto out;
+               orig_entry->flags = flags;
+               goto sync_flags;
        }
 
        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,
        batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
        orig_entry->orig_node = orig_node;
        orig_entry->ttvn = ttvn;
+       orig_entry->flags = flags;
        kref_init(&orig_entry->refcount);
 
        spin_lock_bh(&tt_global->list_lock);
@@ -1582,6 +1616,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
        spin_unlock_bh(&tt_global->list_lock);
        atomic_inc(&tt_global->orig_list_count);
 
+sync_flags:
+       batadv_tt_global_sync_flags(tt_global);
 out:
        if (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,
                }
 
                /* 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
                 */
-               common->flags |= flags;
+               common->flags |= flags & (~BATADV_TT_SYNC_MASK);
 
                /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
                 * 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,
        }
 add_orig_entry:
        /* 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,
                   "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,
                               struct batadv_tt_orig_list_entry *orig,
                               bool best)
 {
+       u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags;
        void *hdr;
        struct batadv_orig_node_vlan *vlan;
        u8 last_ttvn;
@@ -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_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
            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;
 
        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,
                                unsigned short vid)
 {
        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_global_entry *tt_global;
        struct hlist_head *head;
@@ -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
                         * originator
                         */
-                       if (!batadv_tt_global_entry_has_orig(tt_global,
-                                                            orig_node))
+                       tt_orig = batadv_tt_global_orig_entry_find(tt_global,
+                                                                  orig_node);
+                       if (!tt_orig)
                                continue;
 
                        /* 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,
                        /* compute the CRC on flags that have to be kept in sync
                         * among nodes
                         */
-                       flags = tt_common->flags & BATADV_TT_SYNC_MASK;
+                       flags = tt_orig->flags;
                        crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
 
                        crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
+
+                       batadv_tt_orig_list_entry_put(tt_orig);
                }
                rcu_read_unlock();
        }