aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sched/act_mirred.c59
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);
163bad_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
194out:
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
204static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) 211static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)