Commit a006aa51 authored by Linus Lüssing's avatar Linus Lüssing Committed by Simon Wunderlich

batman-adv: bcast: remove remaining skb-copy calls

We currently have two code paths for broadcast packets:

A) self-generated, via batadv_interface_tx()->
   batadv_send_bcast_packet().
B) received/forwarded, via batadv_recv_bcast_packet()->
   batadv_forw_bcast_packet().

For A), self-generated broadcast packets:

The only modifications to the skb data is the ethernet header which is
added/pushed to the skb in
batadv_send_broadcast_skb()->batadv_send_skb_packet(). However before
doing so, batadv_skb_head_push() is called which calls skb_cow_head() to
unshare the space for the to be pushed ethernet header. So for this
case, it is safe to use skb clones.

For B), received/forwarded packets:

The same applies as in A) for the to be forwarded packets. Only the
ethernet header is added. However after (queueing for) forwarding the
packet in batadv_recv_bcast_packet()->batadv_forw_bcast_packet(), a
packet is additionally decapsulated and is sent up the stack through
batadv_recv_bcast_packet()->batadv_interface_rx().

Protocols higher up the stack are already required to check if the
packet is shared and create a copy for further modifications. When the
next (protocol) layer works correctly, it cannot happen that it tries to
operate on the data behind the skb clone which is still queued up for
forwarding.
Co-authored-by: default avatarSven Eckelmann <sven@narfation.org>
Signed-off-by: default avatarSven Eckelmann <sven@narfation.org>
Signed-off-by: default avatarLinus Lüssing <linus.luessing@c0d3.blue>
Signed-off-by: default avatarSimon Wunderlich <sw@simonwunderlich.de>
parent a2b7b148
...@@ -742,6 +742,10 @@ void batadv_forw_packet_ogmv1_queue(struct batadv_priv *bat_priv, ...@@ -742,6 +742,10 @@ void batadv_forw_packet_ogmv1_queue(struct batadv_priv *bat_priv,
* Adds a broadcast packet to the queue and sets up timers. Broadcast packets * Adds a broadcast packet to the queue and sets up timers. Broadcast packets
* are sent multiple times to increase probability for being received. * are sent multiple times to increase probability for being received.
* *
* This call clones the given skb, hence the caller needs to take into
* account that the data segment of the original skb might not be
* modifiable anymore.
*
* Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors. * Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors.
*/ */
static int batadv_forw_bcast_packet_to_list(struct batadv_priv *bat_priv, static int batadv_forw_bcast_packet_to_list(struct batadv_priv *bat_priv,
...@@ -755,7 +759,7 @@ static int batadv_forw_bcast_packet_to_list(struct batadv_priv *bat_priv, ...@@ -755,7 +759,7 @@ static int batadv_forw_bcast_packet_to_list(struct batadv_priv *bat_priv,
unsigned long send_time = jiffies; unsigned long send_time = jiffies;
struct sk_buff *newskb; struct sk_buff *newskb;
newskb = skb_copy(skb, GFP_ATOMIC); newskb = skb_clone(skb, GFP_ATOMIC);
if (!newskb) if (!newskb)
goto err; goto err;
...@@ -794,6 +798,10 @@ static int batadv_forw_bcast_packet_to_list(struct batadv_priv *bat_priv, ...@@ -794,6 +798,10 @@ static int batadv_forw_bcast_packet_to_list(struct batadv_priv *bat_priv,
* or if a delay is given after that. Furthermore, queues additional * or if a delay is given after that. Furthermore, queues additional
* retransmissions if this interface is a wireless one. * retransmissions if this interface is a wireless one.
* *
* This call clones the given skb, hence the caller needs to take into
* account that the data segment of the original skb might not be
* modifiable anymore.
*
* Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors. * Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors.
*/ */
static int batadv_forw_bcast_packet_if(struct batadv_priv *bat_priv, static int batadv_forw_bcast_packet_if(struct batadv_priv *bat_priv,
...@@ -808,7 +816,7 @@ static int batadv_forw_bcast_packet_if(struct batadv_priv *bat_priv, ...@@ -808,7 +816,7 @@ static int batadv_forw_bcast_packet_if(struct batadv_priv *bat_priv,
int ret = NETDEV_TX_OK; int ret = NETDEV_TX_OK;
if (!delay) { if (!delay) {
newskb = skb_copy(skb, GFP_ATOMIC); newskb = skb_clone(skb, GFP_ATOMIC);
if (!newskb) if (!newskb)
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment