diff options
author | Changli Gao <xiaosuo@gmail.com> | 2009-11-17 13:14:00 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-17 13:15:37 +0100 |
commit | feed1f17241d26261e77ddb5f2fc2a91a3c16739 (patch) | |
tree | ff9828b498a5e13dd48277c79a3ef28f0ed62efe /net/sched | |
parent | Phonet: missing rcu_dereference() (diff) | |
download | linux-feed1f17241d26261e77ddb5f2fc2a91a3c16739.tar.xz linux-feed1f17241d26261e77ddb5f2fc2a91a3c16739.zip |
act_mirred: cleanup
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>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/act_mirred.c | 59 |
1 files changed, 33 insertions, 26 deletions
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index b9aaab4e0354..b812c20b66c6 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -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) |