batman-adv: Announce new capability via multicast TVLV
[cascardo/linux.git] / net / batman-adv / originator.c
index 6df12a2..ffd9dfb 100644 (file)
@@ -27,6 +27,7 @@
 #include "bridge_loop_avoidance.h"
 #include "network-coding.h"
 #include "fragmentation.h"
+#include "multicast.h"
 
 /* hash class keys */
 static struct lock_class_key batadv_orig_hash_lock_class_key;
@@ -446,7 +447,7 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
        INIT_HLIST_HEAD(&neigh_node->ifinfo_list);
        spin_lock_init(&neigh_node->ifinfo_lock);
 
-       memcpy(neigh_node->addr, neigh_addr, ETH_ALEN);
+       ether_addr_copy(neigh_node->addr, neigh_addr);
        neigh_node->if_incoming = hard_iface;
        neigh_node->orig_node = orig_node;
 
@@ -457,6 +458,42 @@ out:
        return neigh_node;
 }
 
+/**
+ * batadv_neigh_node_get - retrieve a neighbour from the list
+ * @orig_node: originator which the neighbour belongs to
+ * @hard_iface: the interface where this neighbour is connected to
+ * @addr: the address of the neighbour
+ *
+ * Looks for and possibly returns a neighbour belonging to this originator list
+ * which is connected through the provided hard interface.
+ * Returns NULL if the neighbour is not found.
+ */
+struct batadv_neigh_node *
+batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
+                     const struct batadv_hard_iface *hard_iface,
+                     const uint8_t *addr)
+{
+       struct batadv_neigh_node *tmp_neigh_node, *res = NULL;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) {
+               if (!batadv_compare_eth(tmp_neigh_node->addr, addr))
+                       continue;
+
+               if (tmp_neigh_node->if_incoming != hard_iface)
+                       continue;
+
+               if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+                       continue;
+
+               res = tmp_neigh_node;
+               break;
+       }
+       rcu_read_unlock();
+
+       return res;
+}
+
 /**
  * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object
  * @rcu: rcu pointer of the orig_ifinfo object
@@ -521,6 +558,8 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
        }
        spin_unlock_bh(&orig_node->neigh_list_lock);
 
+       batadv_mcast_purge_orig(orig_node);
+
        /* Free nc_nodes */
        batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
 
@@ -628,15 +667,17 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
        /* extra reference for return */
        atomic_set(&orig_node->refcount, 2);
 
-       orig_node->tt_initialised = false;
        orig_node->bat_priv = bat_priv;
-       memcpy(orig_node->orig, addr, ETH_ALEN);
+       ether_addr_copy(orig_node->orig, addr);
        batadv_dat_init_orig_node_addr(orig_node);
        atomic_set(&orig_node->last_ttvn, 0);
        orig_node->tt_buff = NULL;
        orig_node->tt_buff_len = 0;
        reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
        orig_node->bcast_seqno_reset = reset_time;
+#ifdef CONFIG_BATMAN_ADV_MCAST
+       orig_node->mcast_flags = BATADV_NO_FLAGS;
+#endif
 
        /* create a vlan object for the "untagged" LAN */
        vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);