]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/sched/cls_api.c
Merge tag 'drm/tegra/for-5.6-rc1-fixes' of git://anongit.freedesktop.org/tegra/linux...
[linux.git] / net / sched / cls_api.c
index 20d60b8fcb70c0175bc1a998a9eb80f693c1f8cd..76e0d122616aec71f56ded2b10f696dc1a87c105 100644 (file)
@@ -308,33 +308,12 @@ static void tcf_proto_put(struct tcf_proto *tp, bool rtnl_held,
                tcf_proto_destroy(tp, rtnl_held, true, extack);
 }
 
-static int walker_check_empty(struct tcf_proto *tp, void *fh,
-                             struct tcf_walker *arg)
+static bool tcf_proto_check_delete(struct tcf_proto *tp)
 {
-       if (fh) {
-               arg->nonempty = true;
-               return -1;
-       }
-       return 0;
-}
+       if (tp->ops->delete_empty)
+               return tp->ops->delete_empty(tp);
 
-static bool tcf_proto_is_empty(struct tcf_proto *tp, bool rtnl_held)
-{
-       struct tcf_walker walker = { .fn = walker_check_empty, };
-
-       if (tp->ops->walk) {
-               tp->ops->walk(tp, &walker, rtnl_held);
-               return !walker.nonempty;
-       }
-       return true;
-}
-
-static bool tcf_proto_check_delete(struct tcf_proto *tp, bool rtnl_held)
-{
-       spin_lock(&tp->lock);
-       if (tcf_proto_is_empty(tp, rtnl_held))
-               tp->deleting = true;
-       spin_unlock(&tp->lock);
+       tp->deleting = true;
        return tp->deleting;
 }
 
@@ -626,15 +605,15 @@ static void tcf_chain_flush(struct tcf_chain *chain, bool rtnl_held)
 static int tcf_block_setup(struct tcf_block *block,
                           struct flow_block_offload *bo);
 
-static void tc_indr_block_ing_cmd(struct net_device *dev,
-                                 struct tcf_block *block,
-                                 flow_indr_block_bind_cb_t *cb,
-                                 void *cb_priv,
-                                 enum flow_block_command command)
+static void tc_indr_block_cmd(struct net_device *dev, struct tcf_block *block,
+                             flow_indr_block_bind_cb_t *cb, void *cb_priv,
+                             enum flow_block_command command, bool ingress)
 {
        struct flow_block_offload bo = {
                .command        = command,
-               .binder_type    = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
+               .binder_type    = ingress ?
+                                 FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS :
+                                 FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
                .net            = dev_net(dev),
                .block_shared   = tcf_block_non_null_shared(block),
        };
@@ -652,9 +631,10 @@ static void tc_indr_block_ing_cmd(struct net_device *dev,
        up_write(&block->cb_lock);
 }
 
-static struct tcf_block *tc_dev_ingress_block(struct net_device *dev)
+static struct tcf_block *tc_dev_block(struct net_device *dev, bool ingress)
 {
        const struct Qdisc_class_ops *cops;
+       const struct Qdisc_ops *ops;
        struct Qdisc *qdisc;
 
        if (!dev_ingress_queue(dev))
@@ -664,24 +644,37 @@ static struct tcf_block *tc_dev_ingress_block(struct net_device *dev)
        if (!qdisc)
                return NULL;
 
-       cops = qdisc->ops->cl_ops;
+       ops = qdisc->ops;
+       if (!ops)
+               return NULL;
+
+       if (!ingress && !strcmp("ingress", ops->id))
+               return NULL;
+
+       cops = ops->cl_ops;
        if (!cops)
                return NULL;
 
        if (!cops->tcf_block)
                return NULL;
 
-       return cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
+       return cops->tcf_block(qdisc,
+                              ingress ? TC_H_MIN_INGRESS : TC_H_MIN_EGRESS,
+                              NULL);
 }
 
-static void tc_indr_block_get_and_ing_cmd(struct net_device *dev,
-                                         flow_indr_block_bind_cb_t *cb,
-                                         void *cb_priv,
-                                         enum flow_block_command command)
+static void tc_indr_block_get_and_cmd(struct net_device *dev,
+                                     flow_indr_block_bind_cb_t *cb,
+                                     void *cb_priv,
+                                     enum flow_block_command command)
 {
-       struct tcf_block *block = tc_dev_ingress_block(dev);
+       struct tcf_block *block;
 
-       tc_indr_block_ing_cmd(dev, block, cb, cb_priv, command);
+       block = tc_dev_block(dev, true);
+       tc_indr_block_cmd(dev, block, cb, cb_priv, command, true);
+
+       block = tc_dev_block(dev, false);
+       tc_indr_block_cmd(dev, block, cb, cb_priv, command, false);
 }
 
 static void tc_indr_block_call(struct tcf_block *block,
@@ -1737,7 +1730,7 @@ static void tcf_chain_tp_delete_empty(struct tcf_chain *chain,
         * concurrently.
         * Mark tp for deletion if it is empty.
         */
-       if (!tp_iter || !tcf_proto_check_delete(tp, rtnl_held)) {
+       if (!tp_iter || !tcf_proto_check_delete(tp)) {
                mutex_unlock(&chain->filter_chain_lock);
                return;
        }
@@ -2721,13 +2714,19 @@ static int tc_chain_tmplt_add(struct tcf_chain *chain, struct net *net,
                              struct netlink_ext_ack *extack)
 {
        const struct tcf_proto_ops *ops;
+       char name[IFNAMSIZ];
        void *tmplt_priv;
 
        /* If kind is not set, user did not specify template. */
        if (!tca[TCA_KIND])
                return 0;
 
-       ops = tcf_proto_lookup_ops(nla_data(tca[TCA_KIND]), true, extack);
+       if (tcf_proto_check_kind(tca[TCA_KIND], name)) {
+               NL_SET_ERR_MSG(extack, "Specified TC chain template name too long");
+               return -EINVAL;
+       }
+
+       ops = tcf_proto_lookup_ops(name, true, extack);
        if (IS_ERR(ops))
                return PTR_ERR(ops);
        if (!ops->tmplt_create || !ops->tmplt_destroy || !ops->tmplt_dump) {
@@ -3626,9 +3625,9 @@ static struct pernet_operations tcf_net_ops = {
        .size = sizeof(struct tcf_net),
 };
 
-static struct flow_indr_block_ing_entry block_ing_entry = {
-       .cb = tc_indr_block_get_and_ing_cmd,
-       .list = LIST_HEAD_INIT(block_ing_entry.list),
+static struct flow_indr_block_entry block_entry = {
+       .cb = tc_indr_block_get_and_cmd,
+       .list = LIST_HEAD_INIT(block_entry.list),
 };
 
 static int __init tc_filter_init(void)
@@ -3643,7 +3642,7 @@ static int __init tc_filter_init(void)
        if (err)
                goto err_register_pernet_subsys;
 
-       flow_indr_add_block_ing_cb(&block_ing_entry);
+       flow_indr_add_block_cb(&block_entry);
 
        rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_new_tfilter, NULL,
                      RTNL_FLAG_DOIT_UNLOCKED);