act_mirred: cleanup
authorChangli Gao <xiaosuo@gmail.com>
Tue, 17 Nov 2009 12:14:00 +0000 (04:14 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 17 Nov 2009 12:15:37 +0000 (04:15 -0800)
1. don't let go back using goto.
2. don't call skb_act_clone() until it is necessary.
3. one exit of the critical context.

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/act_mirred.c

index b9aaab4e03548a848c4f9bba9b527803fa602157..b812c20b66c6c2a55e5cf435a61f9ce5ee97e634 100644 (file)
@@ -148,47 +148,39 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
 {
        struct tcf_mirred *m = a->priv;
        struct net_device *dev;
-       struct sk_buff *skb2 = NULL;
-       u32 at = G_TC_AT(skb->tc_verd);
+       struct sk_buff *skb2;
+       u32 at;
+       int retval, err = 1;
 
        spin_lock(&m->tcf_lock);
-
-       dev = m->tcfm_dev;
        m->tcf_tm.lastuse = jiffies;
+       if (m->tcfm_eaction != TCA_EGRESS_MIRROR &&
+           m->tcfm_eaction != TCA_EGRESS_REDIR) {
+               if (net_ratelimit())
+                       printk("tcf_mirred unknown action %d\n",
+                              m->tcfm_eaction);
+               goto out;
+       }
 
-       if (!(dev->flags&IFF_UP) ) {
+       dev = m->tcfm_dev;
+       if (!(dev->flags & IFF_UP)) {
                if (net_ratelimit())
                        printk("mirred to Houston: device %s is gone!\n",
                               dev->name);
-bad_mirred:
-               if (skb2 != NULL)
-                       kfree_skb(skb2);
-               m->tcf_qstats.overlimits++;
-               m->tcf_bstats.bytes += qdisc_pkt_len(skb);
-               m->tcf_bstats.packets++;
-               spin_unlock(&m->tcf_lock);
-               /* should we be asking for packet to be dropped?
-                * may make sense for redirect case only
-               */
-               return TC_ACT_SHOT;
+               goto out;
        }
 
        skb2 = skb_act_clone(skb, GFP_ATOMIC);
        if (skb2 == NULL)
-               goto bad_mirred;
-       if (m->tcfm_eaction != TCA_EGRESS_MIRROR &&
-           m->tcfm_eaction != TCA_EGRESS_REDIR) {
-               if (net_ratelimit())
-                       printk("tcf_mirred unknown action %d\n",
-                              m->tcfm_eaction);
-               goto bad_mirred;
-       }
+               goto out;
 
        m->tcf_bstats.bytes += qdisc_pkt_len(skb2);
        m->tcf_bstats.packets++;
-       if (!(at & AT_EGRESS))
+       at = G_TC_AT(skb->tc_verd);
+       if (!(at & AT_EGRESS)) {
                if (m->tcfm_ok_push)
                        skb_push(skb2, skb2->dev->hard_header_len);
+       }
 
        /* mirror is always swallowed */
        if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
@@ -197,8 +189,23 @@ bad_mirred:
        skb2->dev = dev;
        skb2->iif = skb->dev->ifindex;
        dev_queue_xmit(skb2);
+       err = 0;
+
+out:
+       if (err) {
+               m->tcf_qstats.overlimits++;
+               m->tcf_bstats.bytes += qdisc_pkt_len(skb);
+               m->tcf_bstats.packets++;
+               /* should we be asking for packet to be dropped?
+                * may make sense for redirect case only
+                */
+               retval = TC_ACT_SHOT;
+       } else {
+               retval = m->tcf_action;
+       }
        spin_unlock(&m->tcf_lock);
-       return m->tcf_action;
+
+       return retval;
 }
 
 static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)