linux/net/sched/cls_api.c
<<
>>
Prefs
   1/*
   2 * net/sched/cls_api.c  Packet classifier API.
   3 *
   4 *              This program is free software; you can redistribute it and/or
   5 *              modify it under the terms of the GNU General Public License
   6 *              as published by the Free Software Foundation; either version
   7 *              2 of the License, or (at your option) any later version.
   8 *
   9 * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  10 *
  11 * Changes:
  12 *
  13 * Eduardo J. Blanco <ejbs@netlabs.com.uy> :990222: kmod support
  14 *
  15 */
  16
  17#include <linux/module.h>
  18#include <linux/types.h>
  19#include <linux/kernel.h>
  20#include <linux/string.h>
  21#include <linux/errno.h>
  22#include <linux/skbuff.h>
  23#include <linux/init.h>
  24#include <linux/kmod.h>
  25#include <linux/err.h>
  26#include <linux/slab.h>
  27#include <net/net_namespace.h>
  28#include <net/sock.h>
  29#include <net/netlink.h>
  30#include <net/pkt_sched.h>
  31#include <net/pkt_cls.h>
  32
  33/* The list of all installed classifier types */
  34static LIST_HEAD(tcf_proto_base);
  35
  36/* Protects list of registered TC modules. It is pure SMP lock. */
  37static DEFINE_RWLOCK(cls_mod_lock);
  38
  39/* Find classifier type by string name */
  40
  41static const struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind)
  42{
  43        const struct tcf_proto_ops *t, *res = NULL;
  44
  45        if (kind) {
  46                read_lock(&cls_mod_lock);
  47                list_for_each_entry(t, &tcf_proto_base, head) {
  48                        if (nla_strcmp(kind, t->kind) == 0) {
  49                                if (try_module_get(t->owner))
  50                                        res = t;
  51                                break;
  52                        }
  53                }
  54                read_unlock(&cls_mod_lock);
  55        }
  56        return res;
  57}
  58
  59/* Register(unregister) new classifier type */
  60
  61int register_tcf_proto_ops(struct tcf_proto_ops *ops)
  62{
  63        struct tcf_proto_ops *t;
  64        int rc = -EEXIST;
  65
  66        write_lock(&cls_mod_lock);
  67        list_for_each_entry(t, &tcf_proto_base, head)
  68                if (!strcmp(ops->kind, t->kind))
  69                        goto out;
  70
  71        list_add_tail(&ops->head, &tcf_proto_base);
  72        rc = 0;
  73out:
  74        write_unlock(&cls_mod_lock);
  75        return rc;
  76}
  77EXPORT_SYMBOL(register_tcf_proto_ops);
  78
  79int unregister_tcf_proto_ops(struct tcf_proto_ops *ops)
  80{
  81        struct tcf_proto_ops *t;
  82        int rc = -ENOENT;
  83
  84        /* Wait for outstanding call_rcu()s, if any, from a
  85         * tcf_proto_ops's destroy() handler.
  86         */
  87        rcu_barrier();
  88
  89        write_lock(&cls_mod_lock);
  90        list_for_each_entry(t, &tcf_proto_base, head) {
  91                if (t == ops) {
  92                        list_del(&t->head);
  93                        rc = 0;
  94                        break;
  95                }
  96        }
  97        write_unlock(&cls_mod_lock);
  98        return rc;
  99}
 100EXPORT_SYMBOL(unregister_tcf_proto_ops);
 101
 102static int tfilter_notify(struct net *net, struct sk_buff *oskb,
 103                          struct nlmsghdr *n, struct tcf_proto *tp,
 104                          unsigned long fh, int event, bool unicast);
 105
 106static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
 107                                 struct nlmsghdr *n,
 108                                 struct tcf_proto __rcu **chain, int event)
 109{
 110        struct tcf_proto __rcu **it_chain;
 111        struct tcf_proto *tp;
 112
 113        for (it_chain = chain; (tp = rtnl_dereference(*it_chain)) != NULL;
 114             it_chain = &tp->next)
 115                tfilter_notify(net, oskb, n, tp, 0, event, false);
 116}
 117
 118/* Select new prio value from the range, managed by kernel. */
 119
 120static inline u32 tcf_auto_prio(struct tcf_proto *tp)
 121{
 122        u32 first = TC_H_MAKE(0xC0000000U, 0U);
 123
 124        if (tp)
 125                first = tp->prio - 1;
 126
 127        return first;
 128}
 129
 130/* Add/change/delete/get a filter node */
 131
 132static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
 133{
 134        struct net *net = sock_net(skb->sk);
 135        struct nlattr *tca[TCA_MAX + 1];
 136        struct tcmsg *t;
 137        u32 protocol;
 138        u32 prio;
 139        u32 nprio;
 140        u32 parent;
 141        struct net_device *dev;
 142        struct Qdisc  *q;
 143        struct tcf_proto __rcu **back;
 144        struct tcf_proto __rcu **chain;
 145        struct tcf_proto *tp;
 146        const struct tcf_proto_ops *tp_ops;
 147        const struct Qdisc_class_ops *cops;
 148        unsigned long cl;
 149        unsigned long fh;
 150        int err;
 151        int tp_created;
 152
 153        if ((n->nlmsg_type != RTM_GETTFILTER) &&
 154            !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
 155                return -EPERM;
 156
 157replay:
 158        tp_created = 0;
 159
 160        err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
 161        if (err < 0)
 162                return err;
 163
 164        t = nlmsg_data(n);
 165        protocol = TC_H_MIN(t->tcm_info);
 166        prio = TC_H_MAJ(t->tcm_info);
 167        nprio = prio;
 168        parent = t->tcm_parent;
 169        cl = 0;
 170
 171        if (prio == 0) {
 172                switch (n->nlmsg_type) {
 173                case RTM_DELTFILTER:
 174                        if (protocol || t->tcm_handle || tca[TCA_KIND])
 175                                return -ENOENT;
 176                        break;
 177                case RTM_NEWTFILTER:
 178                        /* If no priority is provided by the user,
 179                         * we allocate one.
 180                         */
 181                        if (n->nlmsg_flags & NLM_F_CREATE) {
 182                                prio = TC_H_MAKE(0x80000000U, 0U);
 183                                break;
 184                        }
 185                        /* fall-through */
 186                default:
 187                        return -ENOENT;
 188                }
 189        }
 190
 191        /* Find head of filter chain. */
 192
 193        /* Find link */
 194        dev = __dev_get_by_index(net, t->tcm_ifindex);
 195        if (dev == NULL)
 196                return -ENODEV;
 197
 198        /* Find qdisc */
 199        if (!parent) {
 200                q = dev->qdisc;
 201                parent = q->handle;
 202        } else {
 203                q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent));
 204                if (q == NULL)
 205                        return -EINVAL;
 206        }
 207
 208        /* Is it classful? */
 209        cops = q->ops->cl_ops;
 210        if (!cops)
 211                return -EINVAL;
 212
 213        if (cops->tcf_chain == NULL)
 214                return -EOPNOTSUPP;
 215
 216        /* Do we search for filter, attached to class? */
 217        if (TC_H_MIN(parent)) {
 218                cl = cops->get(q, parent);
 219                if (cl == 0)
 220                        return -ENOENT;
 221        }
 222
 223        /* And the last stroke */
 224        chain = cops->tcf_chain(q, cl);
 225        err = -EINVAL;
 226        if (chain == NULL)
 227                goto errout;
 228        if (n->nlmsg_type == RTM_DELTFILTER && prio == 0) {
 229                tfilter_notify_chain(net, skb, n, chain, RTM_DELTFILTER);
 230                tcf_destroy_chain(chain);
 231                err = 0;
 232                goto errout;
 233        }
 234
 235        /* Check the chain for existence of proto-tcf with this priority */
 236        for (back = chain;
 237             (tp = rtnl_dereference(*back)) != NULL;
 238             back = &tp->next) {
 239                if (tp->prio >= prio) {
 240                        if (tp->prio == prio) {
 241                                if (!nprio ||
 242                                    (tp->protocol != protocol && protocol))
 243                                        goto errout;
 244                        } else
 245                                tp = NULL;
 246                        break;
 247                }
 248        }
 249
 250        if (tp == NULL) {
 251                /* Proto-tcf does not exist, create new one */
 252
 253                if (tca[TCA_KIND] == NULL || !protocol)
 254                        goto errout;
 255
 256                err = -ENOENT;
 257                if (n->nlmsg_type != RTM_NEWTFILTER ||
 258                    !(n->nlmsg_flags & NLM_F_CREATE))
 259                        goto errout;
 260
 261
 262                /* Create new proto tcf */
 263
 264                err = -ENOBUFS;
 265                tp = kzalloc(sizeof(*tp), GFP_KERNEL);
 266                if (tp == NULL)
 267                        goto errout;
 268                err = -ENOENT;
 269                tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND]);
 270                if (tp_ops == NULL) {
 271#ifdef CONFIG_MODULES
 272                        struct nlattr *kind = tca[TCA_KIND];
 273                        char name[IFNAMSIZ];
 274
 275                        if (kind != NULL &&
 276                            nla_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
 277                                rtnl_unlock();
 278                                request_module("cls_%s", name);
 279                                rtnl_lock();
 280                                tp_ops = tcf_proto_lookup_ops(kind);
 281                                /* We dropped the RTNL semaphore in order to
 282                                 * perform the module load.  So, even if we
 283                                 * succeeded in loading the module we have to
 284                                 * replay the request.  We indicate this using
 285                                 * -EAGAIN.
 286                                 */
 287                                if (tp_ops != NULL) {
 288                                        module_put(tp_ops->owner);
 289                                        err = -EAGAIN;
 290                                }
 291                        }
 292#endif
 293                        kfree(tp);
 294                        goto errout;
 295                }
 296                tp->ops = tp_ops;
 297                tp->protocol = protocol;
 298                tp->prio = nprio ? :
 299                               TC_H_MAJ(tcf_auto_prio(rtnl_dereference(*back)));
 300                tp->q = q;
 301                tp->classify = tp_ops->classify;
 302                tp->classid = parent;
 303
 304                err = tp_ops->init(tp);
 305                if (err != 0) {
 306                        module_put(tp_ops->owner);
 307                        kfree(tp);
 308                        goto errout;
 309                }
 310
 311                tp_created = 1;
 312
 313        } else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind))
 314                goto errout;
 315
 316        fh = tp->ops->get(tp, t->tcm_handle);
 317
 318        if (fh == 0) {
 319                if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
 320                        struct tcf_proto *next = rtnl_dereference(tp->next);
 321
 322                        RCU_INIT_POINTER(*back, next);
 323
 324                        tfilter_notify(net, skb, n, tp, fh,
 325                                       RTM_DELTFILTER, false);
 326                        tcf_destroy(tp, true);
 327                        err = 0;
 328                        goto errout;
 329                }
 330
 331                err = -ENOENT;
 332                if (n->nlmsg_type != RTM_NEWTFILTER ||
 333                    !(n->nlmsg_flags & NLM_F_CREATE))
 334                        goto errout;
 335        } else {
 336                switch (n->nlmsg_type) {
 337                case RTM_NEWTFILTER:
 338                        err = -EEXIST;
 339                        if (n->nlmsg_flags & NLM_F_EXCL) {
 340                                if (tp_created)
 341                                        tcf_destroy(tp, true);
 342                                goto errout;
 343                        }
 344                        break;
 345                case RTM_DELTFILTER:
 346                        err = tp->ops->delete(tp, fh);
 347                        if (err == 0) {
 348                                struct tcf_proto *next = rtnl_dereference(tp->next);
 349
 350                                tfilter_notify(net, skb, n, tp,
 351                                               t->tcm_handle,
 352                                               RTM_DELTFILTER, false);
 353                                if (tcf_destroy(tp, false))
 354                                        RCU_INIT_POINTER(*back, next);
 355                        }
 356                        goto errout;
 357                case RTM_GETTFILTER:
 358                        err = tfilter_notify(net, skb, n, tp, fh,
 359                                             RTM_NEWTFILTER, true);
 360                        goto errout;
 361                default:
 362                        err = -EINVAL;
 363                        goto errout;
 364                }
 365        }
 366
 367        err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
 368                              n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE);
 369        if (err == 0) {
 370                if (tp_created) {
 371                        RCU_INIT_POINTER(tp->next, rtnl_dereference(*back));
 372                        rcu_assign_pointer(*back, tp);
 373                }
 374                tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER, false);
 375        } else {
 376                if (tp_created)
 377                        tcf_destroy(tp, true);
 378        }
 379
 380errout:
 381        if (cl)
 382                cops->put(q, cl);
 383        if (err == -EAGAIN)
 384                /* Replay the request. */
 385                goto replay;
 386        return err;
 387}
 388
 389static int tcf_fill_node(struct net *net, struct sk_buff *skb,
 390                         struct tcf_proto *tp, unsigned long fh, u32 portid,
 391                         u32 seq, u16 flags, int event)
 392{
 393        struct tcmsg *tcm;
 394        struct nlmsghdr  *nlh;
 395        unsigned char *b = skb_tail_pointer(skb);
 396
 397        nlh = nlmsg_put(skb, portid, seq, event, sizeof(*tcm), flags);
 398        if (!nlh)
 399                goto out_nlmsg_trim;
 400        tcm = nlmsg_data(nlh);
 401        tcm->tcm_family = AF_UNSPEC;
 402        tcm->tcm__pad1 = 0;
 403        tcm->tcm__pad2 = 0;
 404        tcm->tcm_ifindex = qdisc_dev(tp->q)->ifindex;
 405        tcm->tcm_parent = tp->classid;
 406        tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
 407        if (nla_put_string(skb, TCA_KIND, tp->ops->kind))
 408                goto nla_put_failure;
 409        tcm->tcm_handle = fh;
 410        if (RTM_DELTFILTER != event) {
 411                tcm->tcm_handle = 0;
 412                if (tp->ops->dump && tp->ops->dump(net, tp, fh, skb, tcm) < 0)
 413                        goto nla_put_failure;
 414        }
 415        nlh->nlmsg_len = skb_tail_pointer(skb) - b;
 416        return skb->len;
 417
 418out_nlmsg_trim:
 419nla_put_failure:
 420        nlmsg_trim(skb, b);
 421        return -1;
 422}
 423
 424static int tfilter_notify(struct net *net, struct sk_buff *oskb,
 425                          struct nlmsghdr *n, struct tcf_proto *tp,
 426                          unsigned long fh, int event, bool unicast)
 427{
 428        struct sk_buff *skb;
 429        u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
 430
 431        skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
 432        if (!skb)
 433                return -ENOBUFS;
 434
 435        if (tcf_fill_node(net, skb, tp, fh, portid, n->nlmsg_seq,
 436                          n->nlmsg_flags, event) <= 0) {
 437                kfree_skb(skb);
 438                return -EINVAL;
 439        }
 440
 441        if (unicast)
 442                return netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT);
 443
 444        return rtnetlink_send(skb, net, portid, RTNLGRP_TC,
 445                              n->nlmsg_flags & NLM_F_ECHO);
 446}
 447
 448struct tcf_dump_args {
 449        struct tcf_walker w;
 450        struct sk_buff *skb;
 451        struct netlink_callback *cb;
 452};
 453
 454static int tcf_node_dump(struct tcf_proto *tp, unsigned long n,
 455                         struct tcf_walker *arg)
 456{
 457        struct tcf_dump_args *a = (void *)arg;
 458        struct net *net = sock_net(a->skb->sk);
 459
 460        return tcf_fill_node(net, a->skb, tp, n, NETLINK_CB(a->cb->skb).portid,
 461                             a->cb->nlh->nlmsg_seq, NLM_F_MULTI,
 462                             RTM_NEWTFILTER);
 463}
 464
 465/* called with RTNL */
 466static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
 467{
 468        struct net *net = sock_net(skb->sk);
 469        int t;
 470        int s_t;
 471        struct net_device *dev;
 472        struct Qdisc *q;
 473        struct tcf_proto *tp, __rcu **chain;
 474        struct tcmsg *tcm = nlmsg_data(cb->nlh);
 475        unsigned long cl = 0;
 476        const struct Qdisc_class_ops *cops;
 477        struct tcf_dump_args arg;
 478
 479        if (nlmsg_len(cb->nlh) < sizeof(*tcm))
 480                return skb->len;
 481        dev = __dev_get_by_index(net, tcm->tcm_ifindex);
 482        if (!dev)
 483                return skb->len;
 484
 485        if (!tcm->tcm_parent)
 486                q = dev->qdisc;
 487        else
 488                q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent));
 489        if (!q)
 490                goto out;
 491        cops = q->ops->cl_ops;
 492        if (!cops)
 493                goto errout;
 494        if (cops->tcf_chain == NULL)
 495                goto errout;
 496        if (TC_H_MIN(tcm->tcm_parent)) {
 497                cl = cops->get(q, tcm->tcm_parent);
 498                if (cl == 0)
 499                        goto errout;
 500        }
 501        chain = cops->tcf_chain(q, cl);
 502        if (chain == NULL)
 503                goto errout;
 504
 505        s_t = cb->args[0];
 506
 507        for (tp = rtnl_dereference(*chain), t = 0;
 508             tp; tp = rtnl_dereference(tp->next), t++) {
 509                if (t < s_t)
 510                        continue;
 511                if (TC_H_MAJ(tcm->tcm_info) &&
 512                    TC_H_MAJ(tcm->tcm_info) != tp->prio)
 513                        continue;
 514                if (TC_H_MIN(tcm->tcm_info) &&
 515                    TC_H_MIN(tcm->tcm_info) != tp->protocol)
 516                        continue;
 517                if (t > s_t)
 518                        memset(&cb->args[1], 0,
 519                               sizeof(cb->args)-sizeof(cb->args[0]));
 520                if (cb->args[1] == 0) {
 521                        if (tcf_fill_node(net, skb, tp, 0,
 522                                          NETLINK_CB(cb->skb).portid,
 523                                          cb->nlh->nlmsg_seq, NLM_F_MULTI,
 524                                          RTM_NEWTFILTER) <= 0)
 525                                break;
 526
 527                        cb->args[1] = 1;
 528                }
 529                if (tp->ops->walk == NULL)
 530                        continue;
 531                arg.w.fn = tcf_node_dump;
 532                arg.skb = skb;
 533                arg.cb = cb;
 534                arg.w.stop = 0;
 535                arg.w.skip = cb->args[1] - 1;
 536                arg.w.count = 0;
 537                tp->ops->walk(tp, &arg.w);
 538                cb->args[1] = arg.w.count + 1;
 539                if (arg.w.stop)
 540                        break;
 541        }
 542
 543        cb->args[0] = t;
 544
 545errout:
 546        if (cl)
 547                cops->put(q, cl);
 548out:
 549        return skb->len;
 550}
 551
 552void tcf_exts_destroy(struct tcf_exts *exts)
 553{
 554#ifdef CONFIG_NET_CLS_ACT
 555        LIST_HEAD(actions);
 556
 557        tcf_exts_to_list(exts, &actions);
 558        tcf_action_destroy(&actions, TCA_ACT_UNBIND);
 559        kfree(exts->actions);
 560        exts->nr_actions = 0;
 561#endif
 562}
 563EXPORT_SYMBOL(tcf_exts_destroy);
 564
 565int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
 566                      struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr)
 567{
 568#ifdef CONFIG_NET_CLS_ACT
 569        {
 570                struct tc_action *act;
 571
 572                if (exts->police && tb[exts->police]) {
 573                        act = tcf_action_init_1(net, tb[exts->police], rate_tlv,
 574                                                "police", ovr, TCA_ACT_BIND);
 575                        if (IS_ERR(act))
 576                                return PTR_ERR(act);
 577
 578                        act->type = exts->type = TCA_OLD_COMPAT;
 579                        exts->actions[0] = act;
 580                        exts->nr_actions = 1;
 581                } else if (exts->action && tb[exts->action]) {
 582                        LIST_HEAD(actions);
 583                        int err, i = 0;
 584
 585                        err = tcf_action_init(net, tb[exts->action], rate_tlv,
 586                                              NULL, ovr, TCA_ACT_BIND,
 587                                              &actions);
 588                        if (err)
 589                                return err;
 590                        list_for_each_entry(act, &actions, list)
 591                                exts->actions[i++] = act;
 592                        exts->nr_actions = i;
 593                }
 594        }
 595#else
 596        if ((exts->action && tb[exts->action]) ||
 597            (exts->police && tb[exts->police]))
 598                return -EOPNOTSUPP;
 599#endif
 600
 601        return 0;
 602}
 603EXPORT_SYMBOL(tcf_exts_validate);
 604
 605void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
 606                     struct tcf_exts *src)
 607{
 608#ifdef CONFIG_NET_CLS_ACT
 609        struct tcf_exts old = *dst;
 610
 611        tcf_tree_lock(tp);
 612        dst->nr_actions = src->nr_actions;
 613        dst->actions = src->actions;
 614        dst->type = src->type;
 615        tcf_tree_unlock(tp);
 616
 617        tcf_exts_destroy(&old);
 618#endif
 619}
 620EXPORT_SYMBOL(tcf_exts_change);
 621
 622#ifdef CONFIG_NET_CLS_ACT
 623static struct tc_action *tcf_exts_first_act(struct tcf_exts *exts)
 624{
 625        if (exts->nr_actions == 0)
 626                return NULL;
 627        else
 628                return exts->actions[0];
 629}
 630#endif
 631
 632int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts)
 633{
 634#ifdef CONFIG_NET_CLS_ACT
 635        struct nlattr *nest;
 636
 637        if (exts->action && exts->nr_actions) {
 638                /*
 639                 * again for backward compatible mode - we want
 640                 * to work with both old and new modes of entering
 641                 * tc data even if iproute2  was newer - jhs
 642                 */
 643                if (exts->type != TCA_OLD_COMPAT) {
 644                        LIST_HEAD(actions);
 645
 646                        nest = nla_nest_start(skb, exts->action);
 647                        if (nest == NULL)
 648                                goto nla_put_failure;
 649
 650                        tcf_exts_to_list(exts, &actions);
 651                        if (tcf_action_dump(skb, &actions, 0, 0) < 0)
 652                                goto nla_put_failure;
 653                        nla_nest_end(skb, nest);
 654                } else if (exts->police) {
 655                        struct tc_action *act = tcf_exts_first_act(exts);
 656                        nest = nla_nest_start(skb, exts->police);
 657                        if (nest == NULL || !act)
 658                                goto nla_put_failure;
 659                        if (tcf_action_dump_old(skb, act, 0, 0) < 0)
 660                                goto nla_put_failure;
 661                        nla_nest_end(skb, nest);
 662                }
 663        }
 664        return 0;
 665
 666nla_put_failure:
 667        nla_nest_cancel(skb, nest);
 668        return -1;
 669#else
 670        return 0;
 671#endif
 672}
 673EXPORT_SYMBOL(tcf_exts_dump);
 674
 675
 676int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts)
 677{
 678#ifdef CONFIG_NET_CLS_ACT
 679        struct tc_action *a = tcf_exts_first_act(exts);
 680        if (a != NULL && tcf_action_copy_stats(skb, a, 1) < 0)
 681                return -1;
 682#endif
 683        return 0;
 684}
 685EXPORT_SYMBOL(tcf_exts_dump_stats);
 686
 687int tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
 688                     struct net_device **hw_dev)
 689{
 690#ifdef CONFIG_NET_CLS_ACT
 691        const struct tc_action *a;
 692        LIST_HEAD(actions);
 693
 694        if (tc_no_actions(exts))
 695                return -EINVAL;
 696
 697        tcf_exts_to_list(exts, &actions);
 698        list_for_each_entry(a, &actions, list) {
 699                if (a->ops->get_dev) {
 700                        a->ops->get_dev(a, dev_net(dev), hw_dev);
 701                        break;
 702                }
 703        }
 704        if (*hw_dev)
 705                return 0;
 706#endif
 707        return -EOPNOTSUPP;
 708}
 709EXPORT_SYMBOL(tcf_exts_get_dev);
 710
 711static int __init tc_filter_init(void)
 712{
 713        rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL, NULL);
 714        rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL, NULL);
 715        rtnl_register(PF_UNSPEC, RTM_GETTFILTER, tc_ctl_tfilter,
 716                      tc_dump_tfilter, NULL);
 717
 718        return 0;
 719}
 720
 721subsys_initcall(tc_filter_init);
 722