net/sched: cls_flower: Set egress_dev mark when calling into the HW driver
[sfrench/cifs-2.6.git] / net / sched / cls_flower.c
index 1a267e77c6de93ad58fd609426d3daef27f39c54..b480d7c792ba03e26e2eece4998f1b82e9c75b05 100644 (file)
@@ -234,6 +234,7 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
        tc_cls_common_offload_init(&cls_flower.common, tp);
        cls_flower.command = TC_CLSFLOWER_DESTROY;
        cls_flower.cookie = (unsigned long) f;
+       cls_flower.egress_dev = f->hw_dev != tp->q->dev_queue->dev;
 
        dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER, &cls_flower);
 }
@@ -289,6 +290,7 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
        cls_flower.command = TC_CLSFLOWER_STATS;
        cls_flower.cookie = (unsigned long) f;
        cls_flower.exts = &f->exts;
+       cls_flower.egress_dev = f->hw_dev != tp->q->dev_queue->dev;
 
        dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
                                      &cls_flower);
@@ -922,28 +924,28 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
 
                if (!tc_flags_valid(fnew->flags)) {
                        err = -EINVAL;
-                       goto errout;
+                       goto errout_idr;
                }
        }
 
        err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr);
        if (err)
-               goto errout;
+               goto errout_idr;
 
        err = fl_check_assign_mask(head, &mask);
        if (err)
-               goto errout;
+               goto errout_idr;
 
        if (!tc_skip_sw(fnew->flags)) {
                if (!fold && fl_lookup(head, &fnew->mkey)) {
                        err = -EEXIST;
-                       goto errout;
+                       goto errout_idr;
                }
 
                err = rhashtable_insert_fast(&head->ht, &fnew->ht_node,
                                             head->ht_params);
                if (err)
-                       goto errout;
+                       goto errout_idr;
        }
 
        if (!tc_skip_hw(fnew->flags)) {
@@ -952,7 +954,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
                                           &mask.key,
                                           fnew);
                if (err)
-                       goto errout;
+                       goto errout_idr;
        }
 
        if (!tc_in_hw(fnew->flags))
@@ -981,6 +983,9 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        kfree(tb);
        return 0;
 
+errout_idr:
+       if (fnew->handle)
+               idr_remove_ext(&head->handle_idr, fnew->handle);
 errout:
        tcf_exts_destroy(&fnew->exts);
        kfree(fnew);