|
@@ -30,6 +30,7 @@
|
|
|
#include <linux/if_ether.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/jiffies.h>
|
|
|
+#include <linux/kernel.h>
|
|
|
#include <linux/list.h>
|
|
|
#include <linux/kref.h>
|
|
|
#include <linux/lockdep.h>
|
|
@@ -58,6 +59,8 @@
|
|
|
#include "send.h"
|
|
|
#include "translation-table.h"
|
|
|
|
|
|
+static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work);
|
|
|
+
|
|
|
/**
|
|
|
* enum batadv_dup_status - duplicate status
|
|
|
* @BATADV_NO_DUP: the packet is no duplicate
|
|
@@ -731,7 +734,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
|
|
|
|
|
|
/* start timer for this packet */
|
|
|
INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
|
|
|
- batadv_send_outstanding_bat_ogm_packet);
|
|
|
+ batadv_iv_send_outstanding_bat_ogm_packet);
|
|
|
queue_delayed_work(batadv_event_workqueue,
|
|
|
&forw_packet_aggr->delayed_work,
|
|
|
send_time - jiffies);
|
|
@@ -938,6 +941,19 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
|
|
u16 tvlv_len = 0;
|
|
|
unsigned long send_time;
|
|
|
|
|
|
+ if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) ||
|
|
|
+ (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED))
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* the interface gets activated here to avoid race conditions between
|
|
|
+ * the moment of activating the interface in
|
|
|
+ * hardif_activate_interface() where the originator mac is set and
|
|
|
+ * outdated packets (especially uninitialized mac addresses) in the
|
|
|
+ * packet queue
|
|
|
+ */
|
|
|
+ if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED)
|
|
|
+ hard_iface->if_status = BATADV_IF_ACTIVE;
|
|
|
+
|
|
|
primary_if = batadv_primary_if_get_selected(bat_priv);
|
|
|
|
|
|
if (hard_iface == primary_if) {
|
|
@@ -1779,6 +1795,45 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
|
|
|
batadv_orig_node_put(orig_node);
|
|
|
}
|
|
|
|
|
|
+static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct delayed_work *delayed_work;
|
|
|
+ struct batadv_forw_packet *forw_packet;
|
|
|
+ struct batadv_priv *bat_priv;
|
|
|
+
|
|
|
+ delayed_work = to_delayed_work(work);
|
|
|
+ forw_packet = container_of(delayed_work, struct batadv_forw_packet,
|
|
|
+ delayed_work);
|
|
|
+ bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
|
|
|
+ spin_lock_bh(&bat_priv->forw_bat_list_lock);
|
|
|
+ hlist_del(&forw_packet->list);
|
|
|
+ spin_unlock_bh(&bat_priv->forw_bat_list_lock);
|
|
|
+
|
|
|
+ if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ batadv_iv_ogm_emit(forw_packet);
|
|
|
+
|
|
|
+ /* we have to have at least one packet in the queue to determine the
|
|
|
+ * queues wake up time unless we are shutting down.
|
|
|
+ *
|
|
|
+ * only re-schedule if this is the "original" copy, e.g. the OGM of the
|
|
|
+ * primary interface should only be rescheduled once per period, but
|
|
|
+ * this function will be called for the forw_packet instances of the
|
|
|
+ * other secondary interfaces as well.
|
|
|
+ */
|
|
|
+ if (forw_packet->own &&
|
|
|
+ forw_packet->if_incoming == forw_packet->if_outgoing)
|
|
|
+ batadv_iv_ogm_schedule(forw_packet->if_incoming);
|
|
|
+
|
|
|
+out:
|
|
|
+ /* don't count own packet */
|
|
|
+ if (!forw_packet->own)
|
|
|
+ atomic_inc(&bat_priv->batman_queue_left);
|
|
|
+
|
|
|
+ batadv_forw_packet_free(forw_packet);
|
|
|
+}
|
|
|
+
|
|
|
static int batadv_iv_ogm_receive(struct sk_buff *skb,
|
|
|
struct batadv_hard_iface *if_incoming)
|
|
|
{
|
|
@@ -1795,7 +1850,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
|
|
|
/* did we receive a B.A.T.M.A.N. IV OGM packet on an interface
|
|
|
* that does not have B.A.T.M.A.N. IV enabled ?
|
|
|
*/
|
|
|
- if (bat_priv->bat_algo_ops->bat_ogm_emit != batadv_iv_ogm_emit)
|
|
|
+ if (bat_priv->bat_algo_ops->bat_iface_enable !=
|
|
|
+ batadv_iv_ogm_iface_enable)
|
|
|
return NET_RX_DROP;
|
|
|
|
|
|
batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX);
|
|
@@ -2053,14 +2109,19 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static void batadv_iv_iface_activate(struct batadv_hard_iface *hard_iface)
|
|
|
+{
|
|
|
+ /* begin scheduling originator messages on that interface */
|
|
|
+ batadv_iv_ogm_schedule(hard_iface);
|
|
|
+}
|
|
|
+
|
|
|
static struct batadv_algo_ops batadv_batman_iv __read_mostly = {
|
|
|
.name = "BATMAN_IV",
|
|
|
+ .bat_iface_activate = batadv_iv_iface_activate,
|
|
|
.bat_iface_enable = batadv_iv_ogm_iface_enable,
|
|
|
.bat_iface_disable = batadv_iv_ogm_iface_disable,
|
|
|
.bat_iface_update_mac = batadv_iv_ogm_iface_update_mac,
|
|
|
.bat_primary_iface_set = batadv_iv_ogm_primary_iface_set,
|
|
|
- .bat_ogm_schedule = batadv_iv_ogm_schedule,
|
|
|
- .bat_ogm_emit = batadv_iv_ogm_emit,
|
|
|
.bat_neigh_cmp = batadv_iv_ogm_neigh_cmp,
|
|
|
.bat_neigh_is_similar_or_better = batadv_iv_ogm_neigh_is_sob,
|
|
|
.bat_neigh_print = batadv_iv_neigh_print,
|