Staging: batman-adv: Aggregate batman packets directly in skb
authorSven Eckelmann <sven.eckelmann@gmx.de>
Sat, 4 Sep 2010 23:58:30 +0000 (01:58 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sun, 5 Sep 2010 07:29:47 +0000 (00:29 -0700)
All originator messages are send through aggregation buffers. Those
buffers can directly be allocated as skb to reduce the cost of
allocation an extra buffer and copying them to a new allocated skb
directly before it gets send.

Now only the skb must be cloned in case of send_packet_to_if as it gets
called by send_packet for each interface. Non-primary ogms must not
cloned at all because they will only send once and the forward_packet
structure is freed by send_outstanding_bat_packet afterwards.

Reported-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/batman-adv/aggregation.c
drivers/staging/batman-adv/send.c
drivers/staging/batman-adv/types.h

index d738b7ab7fc0437fd449d622714cb71f18d21242..5896cf29093887d3d3b1595324c9992cfc11058e 100644 (file)
@@ -39,7 +39,7 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
                               struct forw_packet *forw_packet)
 {
        struct batman_packet *batman_packet =
-               (struct batman_packet *)forw_packet->packet_buff;
+               (struct batman_packet *)forw_packet->skb->data;
        int aggregated_bytes = forw_packet->packet_len + packet_len;
 
        /**
@@ -106,6 +106,7 @@ static void new_aggregated_packet(unsigned char *packet_buff,
 {
        struct forw_packet *forw_packet_aggr;
        unsigned long flags;
+       unsigned char *skb_buff;
        /* FIXME: each batman_if will be attached to a softif */
        struct bat_priv *bat_priv = netdev_priv(soft_device);
 
@@ -125,23 +126,22 @@ static void new_aggregated_packet(unsigned char *packet_buff,
                return;
        }
 
-       forw_packet_aggr->packet_buff = kmalloc(MAX_AGGREGATION_BYTES,
-                                               GFP_ATOMIC);
-       if (!forw_packet_aggr->packet_buff) {
+       forw_packet_aggr->skb = dev_alloc_skb(MAX_AGGREGATION_BYTES +
+                                             sizeof(struct ethhdr));
+       if (!forw_packet_aggr->skb) {
                if (!own_packet)
                        atomic_inc(&bat_priv->batman_queue_left);
                kfree(forw_packet_aggr);
                return;
        }
+       skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr));
 
        INIT_HLIST_NODE(&forw_packet_aggr->list);
 
+       skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
        forw_packet_aggr->packet_len = packet_len;
-       memcpy(forw_packet_aggr->packet_buff,
-              packet_buff,
-              forw_packet_aggr->packet_len);
+       memcpy(skb_buff, packet_buff, packet_len);
 
-       forw_packet_aggr->skb = NULL;
        forw_packet_aggr->own = own_packet;
        forw_packet_aggr->if_incoming = if_incoming;
        forw_packet_aggr->num_packets = 0;
@@ -171,8 +171,10 @@ static void aggregate(struct forw_packet *forw_packet_aggr,
                      int packet_len,
                      bool direct_link)
 {
-       memcpy((forw_packet_aggr->packet_buff + forw_packet_aggr->packet_len),
-              packet_buff, packet_len);
+       unsigned char *skb_buff;
+
+       skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
+       memcpy(skb_buff, packet_buff, packet_len);
        forw_packet_aggr->packet_len += packet_len;
        forw_packet_aggr->num_packets++;
 
index 8dd9dd4af47b4198b4a5f8488e9aaf998f81fe6d..6b138b9015a8037321db26197490eb12a09df39f 100644 (file)
@@ -126,14 +126,14 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
        uint8_t packet_num;
        int16_t buff_pos;
        struct batman_packet *batman_packet;
+       struct sk_buff *skb;
 
        if (batman_if->if_status != IF_ACTIVE)
                return;
 
        packet_num = 0;
        buff_pos = 0;
-       batman_packet = (struct batman_packet *)
-               (forw_packet->packet_buff);
+       batman_packet = (struct batman_packet *)forw_packet->skb->data;
 
        /* adjust all flags and log packets */
        while (aggregated_packet(buff_pos,
@@ -165,12 +165,13 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
                        (batman_packet->num_hna * ETH_ALEN);
                packet_num++;
                batman_packet = (struct batman_packet *)
-                       (forw_packet->packet_buff + buff_pos);
+                       (forw_packet->skb->data + buff_pos);
        }
 
-       send_raw_packet(forw_packet->packet_buff,
-                       forw_packet->packet_len,
-                       batman_if, broadcast_addr);
+       /* create clone because function is called more than once */
+       skb = skb_clone(forw_packet->skb, GFP_ATOMIC);
+       if (skb)
+               send_skb_packet(skb, batman_if, broadcast_addr);
 }
 
 /* send a batman packet */
@@ -180,7 +181,7 @@ static void send_packet(struct forw_packet *forw_packet)
        struct bat_priv *bat_priv = netdev_priv(soft_device);
        struct batman_if *batman_if;
        struct batman_packet *batman_packet =
-               (struct batman_packet *)(forw_packet->packet_buff);
+               (struct batman_packet *)(forw_packet->skb->data);
        unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
 
        if (!forw_packet->if_incoming) {
@@ -206,10 +207,11 @@ static void send_packet(struct forw_packet *forw_packet)
                        batman_packet->ttl, forw_packet->if_incoming->dev,
                        forw_packet->if_incoming->addr_str);
 
-               send_raw_packet(forw_packet->packet_buff,
-                               forw_packet->packet_len,
-                               forw_packet->if_incoming,
+               /* skb is only used once and than forw_packet is free'd */
+               send_skb_packet(forw_packet->skb, forw_packet->if_incoming,
                                broadcast_addr);
+               forw_packet->skb = NULL;
+
                return;
        }
 
@@ -366,7 +368,6 @@ static void forw_packet_free(struct forw_packet *forw_packet)
 {
        if (forw_packet->skb)
                kfree_skb(forw_packet->skb);
-       kfree(forw_packet->packet_buff);
        kfree(forw_packet);
 }
 
@@ -425,7 +426,6 @@ int add_bcast_packet_to_list(struct sk_buff *skb)
        skb_reset_mac_header(skb);
 
        forw_packet->skb = skb;
-       forw_packet->packet_buff = NULL;
 
        /* how often did we send the bcast packet ? */
        forw_packet->num_packets = 0;
index 2b06944a56b5fb67bcc076f0370eab81d3e0a5a0..4b2e832d121c8e1151f61a842aca34b6d7fb74fc 100644 (file)
@@ -161,7 +161,6 @@ struct forw_packet {
        unsigned long send_time;
        uint8_t own;
        struct sk_buff *skb;
-       unsigned char *packet_buff;
        uint16_t packet_len;
        uint32_t direct_link_flags;
        uint8_t num_packets;