|
@@ -26,6 +26,7 @@
|
|
#include <linux/if_ether.h>
|
|
#include <linux/if_ether.h>
|
|
#include <linux/jiffies.h>
|
|
#include <linux/jiffies.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/kernel.h>
|
|
|
|
+#include <linux/kref.h>
|
|
#include <linux/list.h>
|
|
#include <linux/list.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/random.h>
|
|
#include <linux/random.h>
|
|
@@ -176,6 +177,9 @@ static void batadv_v_ogm_send(struct work_struct *work)
|
|
if (hard_iface->soft_iface != bat_priv->soft_iface)
|
|
if (hard_iface->soft_iface != bat_priv->soft_iface)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
+ if (!kref_get_unless_zero(&hard_iface->refcount))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
|
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
|
"Sending own OGM2 packet (originator %pM, seqno %u, throughput %u, TTL %d) on interface %s [%pM]\n",
|
|
"Sending own OGM2 packet (originator %pM, seqno %u, throughput %u, TTL %d) on interface %s [%pM]\n",
|
|
ogm_packet->orig, ntohl(ogm_packet->seqno),
|
|
ogm_packet->orig, ntohl(ogm_packet->seqno),
|
|
@@ -185,10 +189,13 @@ static void batadv_v_ogm_send(struct work_struct *work)
|
|
|
|
|
|
/* this skb gets consumed by batadv_v_ogm_send_to_if() */
|
|
/* this skb gets consumed by batadv_v_ogm_send_to_if() */
|
|
skb_tmp = skb_clone(skb, GFP_ATOMIC);
|
|
skb_tmp = skb_clone(skb, GFP_ATOMIC);
|
|
- if (!skb_tmp)
|
|
|
|
|
|
+ if (!skb_tmp) {
|
|
|
|
+ batadv_hardif_put(hard_iface);
|
|
break;
|
|
break;
|
|
|
|
+ }
|
|
|
|
|
|
batadv_v_ogm_send_to_if(skb_tmp, hard_iface);
|
|
batadv_v_ogm_send_to_if(skb_tmp, hard_iface);
|
|
|
|
+ batadv_hardif_put(hard_iface);
|
|
}
|
|
}
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
|
|
|
|
@@ -704,9 +711,14 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
|
|
if (hard_iface->soft_iface != bat_priv->soft_iface)
|
|
if (hard_iface->soft_iface != bat_priv->soft_iface)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
+ if (!kref_get_unless_zero(&hard_iface->refcount))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet,
|
|
batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet,
|
|
orig_node, neigh_node,
|
|
orig_node, neigh_node,
|
|
if_incoming, hard_iface);
|
|
if_incoming, hard_iface);
|
|
|
|
+
|
|
|
|
+ batadv_hardif_put(hard_iface);
|
|
}
|
|
}
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
out:
|
|
out:
|