batman-adv: Introduce forward packet creation helper
This patch abstracts the forward packet creation into the new function batadv_forw_packet_alloc(). The queue counting and interface reference counters are now handled internally within batadv_forw_packet_alloc() and its batadv_forw_packet_free() counterpart. This should reduce the risk of having reference/queue counting bugs again and should increase code readibility. Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
This commit is contained in:
committed by
Simon Wunderlich
parent
4fd261bf58
commit
a65e548131
@ -439,6 +439,13 @@ int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
BATADV_P_DATA, orig_node, vid);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_forw_packet_free - free a forwarding packet
|
||||
* @forw_packet: The packet to free
|
||||
*
|
||||
* This frees a forwarding packet and releases any resources it might
|
||||
* have claimed.
|
||||
*/
|
||||
void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet)
|
||||
{
|
||||
kfree_skb(forw_packet->skb);
|
||||
@ -446,9 +453,73 @@ void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet)
|
||||
batadv_hardif_put(forw_packet->if_incoming);
|
||||
if (forw_packet->if_outgoing)
|
||||
batadv_hardif_put(forw_packet->if_outgoing);
|
||||
if (forw_packet->queue_left)
|
||||
atomic_inc(forw_packet->queue_left);
|
||||
kfree(forw_packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_forw_packet_alloc - allocate a forwarding packet
|
||||
* @if_incoming: The (optional) if_incoming to be grabbed
|
||||
* @if_outgoing: The (optional) if_outgoing to be grabbed
|
||||
* @queue_left: The (optional) queue counter to decrease
|
||||
* @bat_priv: The bat_priv for the mesh of this forw_packet
|
||||
*
|
||||
* Allocates a forwarding packet and tries to get a reference to the
|
||||
* (optional) if_incoming, if_outgoing and queue_left. If queue_left
|
||||
* is NULL then bat_priv is optional, too.
|
||||
*
|
||||
* Return: An allocated forwarding packet on success, NULL otherwise.
|
||||
*/
|
||||
struct batadv_forw_packet *
|
||||
batadv_forw_packet_alloc(struct batadv_hard_iface *if_incoming,
|
||||
struct batadv_hard_iface *if_outgoing,
|
||||
atomic_t *queue_left,
|
||||
struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_forw_packet *forw_packet;
|
||||
const char *qname;
|
||||
|
||||
if (queue_left && !batadv_atomic_dec_not_zero(queue_left)) {
|
||||
qname = "unknown";
|
||||
|
||||
if (queue_left == &bat_priv->bcast_queue_left)
|
||||
qname = "bcast";
|
||||
|
||||
if (queue_left == &bat_priv->batman_queue_left)
|
||||
qname = "batman";
|
||||
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"%s queue is full\n", qname);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
forw_packet = kmalloc(sizeof(*forw_packet), GFP_ATOMIC);
|
||||
if (!forw_packet)
|
||||
goto err;
|
||||
|
||||
if (if_incoming)
|
||||
kref_get(&if_incoming->refcount);
|
||||
|
||||
if (if_outgoing)
|
||||
kref_get(&if_outgoing->refcount);
|
||||
|
||||
forw_packet->skb = NULL;
|
||||
forw_packet->queue_left = queue_left;
|
||||
forw_packet->if_incoming = if_incoming;
|
||||
forw_packet->if_outgoing = if_outgoing;
|
||||
forw_packet->num_packets = 0;
|
||||
|
||||
return forw_packet;
|
||||
|
||||
err:
|
||||
if (queue_left)
|
||||
atomic_inc(queue_left);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
|
||||
struct batadv_forw_packet *forw_packet,
|
||||
@ -487,24 +558,20 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
|
||||
struct batadv_bcast_packet *bcast_packet;
|
||||
struct sk_buff *newskb;
|
||||
|
||||
if (!batadv_atomic_dec_not_zero(&bat_priv->bcast_queue_left)) {
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"bcast packet queue full\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if)
|
||||
goto out_and_inc;
|
||||
|
||||
forw_packet = kmalloc(sizeof(*forw_packet), GFP_ATOMIC);
|
||||
goto err;
|
||||
|
||||
forw_packet = batadv_forw_packet_alloc(primary_if, NULL,
|
||||
&bat_priv->bcast_queue_left,
|
||||
bat_priv);
|
||||
batadv_hardif_put(primary_if);
|
||||
if (!forw_packet)
|
||||
goto out_and_inc;
|
||||
goto err;
|
||||
|
||||
newskb = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!newskb)
|
||||
goto packet_free;
|
||||
goto err_packet_free;
|
||||
|
||||
/* as we have a copy now, it is safe to decrease the TTL */
|
||||
bcast_packet = (struct batadv_bcast_packet *)newskb->data;
|
||||
@ -513,11 +580,6 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
|
||||
skb_reset_mac_header(newskb);
|
||||
|
||||
forw_packet->skb = newskb;
|
||||
forw_packet->if_incoming = primary_if;
|
||||
forw_packet->if_outgoing = NULL;
|
||||
|
||||
/* how often did we send the bcast packet ? */
|
||||
forw_packet->num_packets = 0;
|
||||
|
||||
INIT_DELAYED_WORK(&forw_packet->delayed_work,
|
||||
batadv_send_outstanding_bcast_packet);
|
||||
@ -525,13 +587,9 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
|
||||
_batadv_add_bcast_packet_to_list(bat_priv, forw_packet, delay);
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
packet_free:
|
||||
kfree(forw_packet);
|
||||
out_and_inc:
|
||||
atomic_inc(&bat_priv->bcast_queue_left);
|
||||
out:
|
||||
if (primary_if)
|
||||
batadv_hardif_put(primary_if);
|
||||
err_packet_free:
|
||||
batadv_forw_packet_free(forw_packet);
|
||||
err:
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
@ -592,7 +650,6 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
|
||||
|
||||
out:
|
||||
batadv_forw_packet_free(forw_packet);
|
||||
atomic_inc(&bat_priv->bcast_queue_left);
|
||||
}
|
||||
|
||||
void
|
||||
@ -633,9 +690,6 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
|
||||
|
||||
if (pending) {
|
||||
hlist_del(&forw_packet->list);
|
||||
if (!forw_packet->own)
|
||||
atomic_inc(&bat_priv->bcast_queue_left);
|
||||
|
||||
batadv_forw_packet_free(forw_packet);
|
||||
}
|
||||
}
|
||||
@ -663,9 +717,6 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
|
||||
|
||||
if (pending) {
|
||||
hlist_del(&forw_packet->list);
|
||||
if (!forw_packet->own)
|
||||
atomic_inc(&bat_priv->batman_queue_left);
|
||||
|
||||
batadv_forw_packet_free(forw_packet);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user