diff options
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r-- | net/sched/sch_api.c | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index e7f8e4bfd4ec..929b024f41ba 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <net/sock.h> | 35 | #include <net/sock.h> |
36 | #include <net/netlink.h> | 36 | #include <net/netlink.h> |
37 | #include <net/pkt_sched.h> | 37 | #include <net/pkt_sched.h> |
38 | #include <net/pkt_cls.h> | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | 41 | ||
@@ -1648,6 +1649,64 @@ static int tclass_del_notify(struct net *net, | |||
1648 | n->nlmsg_flags & NLM_F_ECHO); | 1649 | n->nlmsg_flags & NLM_F_ECHO); |
1649 | } | 1650 | } |
1650 | 1651 | ||
1652 | #ifdef CONFIG_NET_CLS | ||
1653 | |||
1654 | struct tcf_bind_args { | ||
1655 | struct tcf_walker w; | ||
1656 | u32 classid; | ||
1657 | unsigned long cl; | ||
1658 | }; | ||
1659 | |||
1660 | static int tcf_node_bind(struct tcf_proto *tp, void *n, struct tcf_walker *arg) | ||
1661 | { | ||
1662 | struct tcf_bind_args *a = (void *)arg; | ||
1663 | |||
1664 | if (tp->ops->bind_class) { | ||
1665 | tcf_tree_lock(tp); | ||
1666 | tp->ops->bind_class(n, a->classid, a->cl); | ||
1667 | tcf_tree_unlock(tp); | ||
1668 | } | ||
1669 | return 0; | ||
1670 | } | ||
1671 | |||
1672 | static void tc_bind_tclass(struct Qdisc *q, u32 portid, u32 clid, | ||
1673 | unsigned long new_cl) | ||
1674 | { | ||
1675 | const struct Qdisc_class_ops *cops = q->ops->cl_ops; | ||
1676 | struct tcf_block *block; | ||
1677 | struct tcf_chain *chain; | ||
1678 | unsigned long cl; | ||
1679 | |||
1680 | cl = cops->find(q, portid); | ||
1681 | if (!cl) | ||
1682 | return; | ||
1683 | block = cops->tcf_block(q, cl); | ||
1684 | if (!block) | ||
1685 | return; | ||
1686 | list_for_each_entry(chain, &block->chain_list, list) { | ||
1687 | struct tcf_proto *tp; | ||
1688 | |||
1689 | for (tp = rtnl_dereference(chain->filter_chain); | ||
1690 | tp; tp = rtnl_dereference(tp->next)) { | ||
1691 | struct tcf_bind_args arg = {}; | ||
1692 | |||
1693 | arg.w.fn = tcf_node_bind; | ||
1694 | arg.classid = clid; | ||
1695 | arg.cl = new_cl; | ||
1696 | tp->ops->walk(tp, &arg.w); | ||
1697 | } | ||
1698 | } | ||
1699 | } | ||
1700 | |||
1701 | #else | ||
1702 | |||
1703 | static void tc_bind_tclass(struct Qdisc *q, u32 portid, u32 clid, | ||
1704 | unsigned long new_cl) | ||
1705 | { | ||
1706 | } | ||
1707 | |||
1708 | #endif | ||
1709 | |||
1651 | static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, | 1710 | static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, |
1652 | struct netlink_ext_ack *extack) | 1711 | struct netlink_ext_ack *extack) |
1653 | { | 1712 | { |
@@ -1753,6 +1812,8 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, | |||
1753 | break; | 1812 | break; |
1754 | case RTM_DELTCLASS: | 1813 | case RTM_DELTCLASS: |
1755 | err = tclass_del_notify(net, cops, skb, n, q, cl); | 1814 | err = tclass_del_notify(net, cops, skb, n, q, cl); |
1815 | /* Unbind the class with flilters with 0 */ | ||
1816 | tc_bind_tclass(q, portid, clid, 0); | ||
1756 | goto out; | 1817 | goto out; |
1757 | case RTM_GETTCLASS: | 1818 | case RTM_GETTCLASS: |
1758 | err = tclass_notify(net, skb, n, q, cl, RTM_NEWTCLASS); | 1819 | err = tclass_notify(net, skb, n, q, cl, RTM_NEWTCLASS); |
@@ -1767,9 +1828,12 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, | |||
1767 | err = -EOPNOTSUPP; | 1828 | err = -EOPNOTSUPP; |
1768 | if (cops->change) | 1829 | if (cops->change) |
1769 | err = cops->change(q, clid, portid, tca, &new_cl); | 1830 | err = cops->change(q, clid, portid, tca, &new_cl); |
1770 | if (err == 0) | 1831 | if (err == 0) { |
1771 | tclass_notify(net, skb, n, q, new_cl, RTM_NEWTCLASS); | 1832 | tclass_notify(net, skb, n, q, new_cl, RTM_NEWTCLASS); |
1772 | 1833 | /* We just create a new class, need to do reverse binding. */ | |
1834 | if (cl != new_cl) | ||
1835 | tc_bind_tclass(q, portid, clid, new_cl); | ||
1836 | } | ||
1773 | out: | 1837 | out: |
1774 | return err; | 1838 | return err; |
1775 | } | 1839 | } |