llc: avoid skb_clone() if there is only one handler
authorChangli Gao <xiaosuo@gmail.com>
Tue, 22 Feb 2011 01:55:18 +0000 (01:55 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Feb 2011 20:28:50 +0000 (12:28 -0800)
Signed-off-by: Changli Gao <xiaosuo@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/llc/llc_input.c

index f996874..058f1e9 100644 (file)
@@ -181,25 +181,26 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
         * LLC functionality
         */
        rcv = rcu_dereference(sap->rcv_func);
-       if (rcv) {
-               struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
-               if (cskb)
-                       rcv(cskb, dev, pt, orig_dev);
-       }
        dest = llc_pdu_type(skb);
-       if (unlikely(!dest || !llc_type_handlers[dest - 1]))
-               goto drop_put;
-       llc_type_handlers[dest - 1](sap, skb);
-out_put:
+       if (unlikely(!dest || !llc_type_handlers[dest - 1])) {
+               if (rcv)
+                       rcv(skb, dev, pt, orig_dev);
+               else
+                       kfree_skb(skb);
+       } else {
+               if (rcv) {
+                       struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
+                       if (cskb)
+                               rcv(cskb, dev, pt, orig_dev);
+               }
+               llc_type_handlers[dest - 1](sap, skb);
+       }
        llc_sap_put(sap);
 out:
        return 0;
 drop:
        kfree_skb(skb);
        goto out;
-drop_put:
-       kfree_skb(skb);
-       goto out_put;
 handle_station:
        if (!llc_station_handler)
                goto drop;