diff options
| -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, | |||
| 148 | { | 148 | { |
| 149 | struct tcf_mirred *m = a->priv; | 149 | struct tcf_mirred *m = a->priv; |
| 150 | struct net_device *dev; | 150 | struct net_device *dev; |
| 151 | struct sk_buff *skb2 = NULL; | 151 | struct sk_buff *skb2; |
| 152 | u32 at = G_TC_AT(skb->tc_verd); | 152 | u32 at; |
| 153 | int retval, err = 1; | ||
| 153 | 154 | ||
| 154 | spin_lock(&m->tcf_lock); | 155 | spin_lock(&m->tcf_lock); |
| 155 | |||
| 156 | dev = m->tcfm_dev; | ||
| 157 | m->tcf_tm.lastuse = jiffies; | 156 | m->tcf_tm.lastuse = jiffies; |
| 157 | if (m->tcfm_eaction != TCA_EGRESS_MIRROR && | ||
| 158 | m->tcfm_eaction != TCA_EGRESS_REDIR) { | ||
| 159 | if (net_ratelimit()) | ||
| 160 | printk("tcf_mirred unknown action %d\n", | ||
| 161 | m->tcfm_eaction); | ||
| 162 | goto out; | ||
| 163 | } | ||
| 158 | 164 | ||
| 159 | if (!(dev->flags&IFF_UP) ) { | 165 | dev = m->tcfm_dev; |
| 166 | if (!(dev->flags & IFF_UP)) { | ||
| 160 | if (net_ratelimit()) | 167 | if (net_ratelimit()) |
| 161 | printk("mirred to Houston: device %s is gone!\n", | 168 | printk("mirred to Houston: device %s is gone!\n", |
| 162 | dev->name); | 169 | dev->name); |
| 163 | bad_mirred: | 170 | goto out; |
| 164 | if (skb2 != NULL) | ||
| 165 | kfree_skb(skb2); | ||
| 166 | m->tcf_qstats.overlimits++; | ||
| 167 | m->tcf_bstats.bytes += qdisc_pkt_len(skb); | ||
| 168 | m->tcf_bstats.packets++; | ||
| 169 | spin_unlock(&m->tcf_lock); | ||
| 170 | /* should we be asking for packet to be dropped? | ||
| 171 | * may make sense for redirect case only | ||
| 172 | */ | ||
| 173 | return TC_ACT_SHOT; | ||
| 174 | } | 171 | } |
| 175 | 172 | ||
| 176 | skb2 = skb_act_clone(skb, GFP_ATOMIC); | 173 | skb2 = skb_act_clone(skb, GFP_ATOMIC); |
| 177 | if (skb2 == NULL) | 174 | if (skb2 == NULL) |
| 178 | goto bad_mirred; | 175 | goto out; |
| 179 | if (m->tcfm_eaction != TCA_EGRESS_MIRROR && | ||
| 180 | m->tcfm_eaction != TCA_EGRESS_REDIR) { | ||
| 181 | if (net_ratelimit()) | ||
| 182 | printk("tcf_mirred unknown action %d\n", | ||
| 183 | m->tcfm_eaction); | ||
| 184 | goto bad_mirred; | ||
| 185 | } | ||
| 186 | 176 | ||
| 187 | m->tcf_bstats.bytes += qdisc_pkt_len(skb2); | 177 | m->tcf_bstats.bytes += qdisc_pkt_len(skb2); |
| 188 | m->tcf_bstats.packets++; | 178 | m->tcf_bstats.packets++; |
| 189 | if (!(at & AT_EGRESS)) | 179 | at = G_TC_AT(skb->tc_verd); |
| 180 | if (!(at & AT_EGRESS)) { | ||
| 190 | if (m->tcfm_ok_push) | 181 | if (m->tcfm_ok_push) |
| 191 | skb_push(skb2, skb2->dev->hard_header_len); | 182 | skb_push(skb2, skb2->dev->hard_header_len); |
| 183 | } | ||
| 192 | 184 | ||
| 193 | /* mirror is always swallowed */ | 185 | /* mirror is always swallowed */ |
| 194 | if (m->tcfm_eaction != TCA_EGRESS_MIRROR) | 186 | if (m->tcfm_eaction != TCA_EGRESS_MIRROR) |
| @@ -197,8 +189,23 @@ bad_mirred: | |||
| 197 | skb2->dev = dev; | 189 | skb2->dev = dev; |
| 198 | skb2->iif = skb->dev->ifindex; | 190 | skb2->iif = skb->dev->ifindex; |
| 199 | dev_queue_xmit(skb2); | 191 | dev_queue_xmit(skb2); |
| 192 | err = 0; | ||
| 193 | |||
| 194 | out: | ||
| 195 | if (err) { | ||
| 196 | m->tcf_qstats.overlimits++; | ||
| 197 | m->tcf_bstats.bytes += qdisc_pkt_len(skb); | ||
| 198 | m->tcf_bstats.packets++; | ||
| 199 | /* should we be asking for packet to be dropped? | ||
| 200 | * may make sense for redirect case only | ||
| 201 | */ | ||
| 202 | retval = TC_ACT_SHOT; | ||
| 203 | } else { | ||
| 204 | retval = m->tcf_action; | ||
| 205 | } | ||
| 200 | spin_unlock(&m->tcf_lock); | 206 | spin_unlock(&m->tcf_lock); |
| 201 | return m->tcf_action; | 207 | |
| 208 | return retval; | ||
| 202 | } | 209 | } |
| 203 | 210 | ||
| 204 | static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 211 | static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
