diff options
-rw-r--r-- | include/net/sch_generic.h | 1 | ||||
-rw-r--r-- | net/sched/cls_basic.c | 9 | ||||
-rw-r--r-- | net/sched/cls_bpf.c | 9 | ||||
-rw-r--r-- | net/sched/cls_flower.c | 9 | ||||
-rw-r--r-- | net/sched/cls_fw.c | 9 | ||||
-rw-r--r-- | net/sched/cls_matchall.c | 9 | ||||
-rw-r--r-- | net/sched/cls_route.c | 9 | ||||
-rw-r--r-- | net/sched/cls_rsvp.h | 9 | ||||
-rw-r--r-- | net/sched/cls_tcindex.c | 9 | ||||
-rw-r--r-- | net/sched/cls_u32.c | 9 | ||||
-rw-r--r-- | net/sched/sch_api.c | 68 |
11 files changed, 148 insertions, 2 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index c30b634c5f82..d6247a3c40df 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -217,6 +217,7 @@ struct tcf_proto_ops { | |||
217 | void **, bool); | 217 | void **, bool); |
218 | int (*delete)(struct tcf_proto*, void *, bool*); | 218 | int (*delete)(struct tcf_proto*, void *, bool*); |
219 | void (*walk)(struct tcf_proto*, struct tcf_walker *arg); | 219 | void (*walk)(struct tcf_proto*, struct tcf_walker *arg); |
220 | void (*bind_class)(void *, u32, unsigned long); | ||
220 | 221 | ||
221 | /* rtnetlink specific */ | 222 | /* rtnetlink specific */ |
222 | int (*dump)(struct net*, struct tcf_proto*, void *, | 223 | int (*dump)(struct net*, struct tcf_proto*, void *, |
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 73cc7f167a38..d89ebafd2239 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -235,6 +235,14 @@ skip: | |||
235 | } | 235 | } |
236 | } | 236 | } |
237 | 237 | ||
238 | static void basic_bind_class(void *fh, u32 classid, unsigned long cl) | ||
239 | { | ||
240 | struct basic_filter *f = fh; | ||
241 | |||
242 | if (f && f->res.classid == classid) | ||
243 | f->res.class = cl; | ||
244 | } | ||
245 | |||
238 | static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh, | 246 | static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh, |
239 | struct sk_buff *skb, struct tcmsg *t) | 247 | struct sk_buff *skb, struct tcmsg *t) |
240 | { | 248 | { |
@@ -280,6 +288,7 @@ static struct tcf_proto_ops cls_basic_ops __read_mostly = { | |||
280 | .delete = basic_delete, | 288 | .delete = basic_delete, |
281 | .walk = basic_walk, | 289 | .walk = basic_walk, |
282 | .dump = basic_dump, | 290 | .dump = basic_dump, |
291 | .bind_class = basic_bind_class, | ||
283 | .owner = THIS_MODULE, | 292 | .owner = THIS_MODULE, |
284 | }; | 293 | }; |
285 | 294 | ||
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 6f2dffe30f25..520c5027646a 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
@@ -607,6 +607,14 @@ nla_put_failure: | |||
607 | return -1; | 607 | return -1; |
608 | } | 608 | } |
609 | 609 | ||
610 | static void cls_bpf_bind_class(void *fh, u32 classid, unsigned long cl) | ||
611 | { | ||
612 | struct cls_bpf_prog *prog = fh; | ||
613 | |||
614 | if (prog && prog->res.classid == classid) | ||
615 | prog->res.class = cl; | ||
616 | } | ||
617 | |||
610 | static void cls_bpf_walk(struct tcf_proto *tp, struct tcf_walker *arg) | 618 | static void cls_bpf_walk(struct tcf_proto *tp, struct tcf_walker *arg) |
611 | { | 619 | { |
612 | struct cls_bpf_head *head = rtnl_dereference(tp->root); | 620 | struct cls_bpf_head *head = rtnl_dereference(tp->root); |
@@ -635,6 +643,7 @@ static struct tcf_proto_ops cls_bpf_ops __read_mostly = { | |||
635 | .delete = cls_bpf_delete, | 643 | .delete = cls_bpf_delete, |
636 | .walk = cls_bpf_walk, | 644 | .walk = cls_bpf_walk, |
637 | .dump = cls_bpf_dump, | 645 | .dump = cls_bpf_dump, |
646 | .bind_class = cls_bpf_bind_class, | ||
638 | }; | 647 | }; |
639 | 648 | ||
640 | static int __init cls_bpf_init_mod(void) | 649 | static int __init cls_bpf_init_mod(void) |
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 3d041d279b92..1a267e77c6de 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c | |||
@@ -1351,6 +1351,14 @@ nla_put_failure: | |||
1351 | return -1; | 1351 | return -1; |
1352 | } | 1352 | } |
1353 | 1353 | ||
1354 | static void fl_bind_class(void *fh, u32 classid, unsigned long cl) | ||
1355 | { | ||
1356 | struct cls_fl_filter *f = fh; | ||
1357 | |||
1358 | if (f && f->res.classid == classid) | ||
1359 | f->res.class = cl; | ||
1360 | } | ||
1361 | |||
1354 | static struct tcf_proto_ops cls_fl_ops __read_mostly = { | 1362 | static struct tcf_proto_ops cls_fl_ops __read_mostly = { |
1355 | .kind = "flower", | 1363 | .kind = "flower", |
1356 | .classify = fl_classify, | 1364 | .classify = fl_classify, |
@@ -1361,6 +1369,7 @@ static struct tcf_proto_ops cls_fl_ops __read_mostly = { | |||
1361 | .delete = fl_delete, | 1369 | .delete = fl_delete, |
1362 | .walk = fl_walk, | 1370 | .walk = fl_walk, |
1363 | .dump = fl_dump, | 1371 | .dump = fl_dump, |
1372 | .bind_class = fl_bind_class, | ||
1364 | .owner = THIS_MODULE, | 1373 | .owner = THIS_MODULE, |
1365 | }; | 1374 | }; |
1366 | 1375 | ||
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 192255ec50bd..941245ad07fd 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c | |||
@@ -412,6 +412,14 @@ nla_put_failure: | |||
412 | return -1; | 412 | return -1; |
413 | } | 413 | } |
414 | 414 | ||
415 | static void fw_bind_class(void *fh, u32 classid, unsigned long cl) | ||
416 | { | ||
417 | struct fw_filter *f = fh; | ||
418 | |||
419 | if (f && f->res.classid == classid) | ||
420 | f->res.class = cl; | ||
421 | } | ||
422 | |||
415 | static struct tcf_proto_ops cls_fw_ops __read_mostly = { | 423 | static struct tcf_proto_ops cls_fw_ops __read_mostly = { |
416 | .kind = "fw", | 424 | .kind = "fw", |
417 | .classify = fw_classify, | 425 | .classify = fw_classify, |
@@ -422,6 +430,7 @@ static struct tcf_proto_ops cls_fw_ops __read_mostly = { | |||
422 | .delete = fw_delete, | 430 | .delete = fw_delete, |
423 | .walk = fw_walk, | 431 | .walk = fw_walk, |
424 | .dump = fw_dump, | 432 | .dump = fw_dump, |
433 | .bind_class = fw_bind_class, | ||
425 | .owner = THIS_MODULE, | 434 | .owner = THIS_MODULE, |
426 | }; | 435 | }; |
427 | 436 | ||
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c index d4dc387f7a56..21cc45caf842 100644 --- a/net/sched/cls_matchall.c +++ b/net/sched/cls_matchall.c | |||
@@ -251,6 +251,14 @@ nla_put_failure: | |||
251 | return -1; | 251 | return -1; |
252 | } | 252 | } |
253 | 253 | ||
254 | static void mall_bind_class(void *fh, u32 classid, unsigned long cl) | ||
255 | { | ||
256 | struct cls_mall_head *head = fh; | ||
257 | |||
258 | if (head && head->res.classid == classid) | ||
259 | head->res.class = cl; | ||
260 | } | ||
261 | |||
254 | static struct tcf_proto_ops cls_mall_ops __read_mostly = { | 262 | static struct tcf_proto_ops cls_mall_ops __read_mostly = { |
255 | .kind = "matchall", | 263 | .kind = "matchall", |
256 | .classify = mall_classify, | 264 | .classify = mall_classify, |
@@ -261,6 +269,7 @@ static struct tcf_proto_ops cls_mall_ops __read_mostly = { | |||
261 | .delete = mall_delete, | 269 | .delete = mall_delete, |
262 | .walk = mall_walk, | 270 | .walk = mall_walk, |
263 | .dump = mall_dump, | 271 | .dump = mall_dump, |
272 | .bind_class = mall_bind_class, | ||
264 | .owner = THIS_MODULE, | 273 | .owner = THIS_MODULE, |
265 | }; | 274 | }; |
266 | 275 | ||
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index 3b70982394ce..9ddde65915d2 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c | |||
@@ -624,6 +624,14 @@ nla_put_failure: | |||
624 | return -1; | 624 | return -1; |
625 | } | 625 | } |
626 | 626 | ||
627 | static void route4_bind_class(void *fh, u32 classid, unsigned long cl) | ||
628 | { | ||
629 | struct route4_filter *f = fh; | ||
630 | |||
631 | if (f && f->res.classid == classid) | ||
632 | f->res.class = cl; | ||
633 | } | ||
634 | |||
627 | static struct tcf_proto_ops cls_route4_ops __read_mostly = { | 635 | static struct tcf_proto_ops cls_route4_ops __read_mostly = { |
628 | .kind = "route", | 636 | .kind = "route", |
629 | .classify = route4_classify, | 637 | .classify = route4_classify, |
@@ -634,6 +642,7 @@ static struct tcf_proto_ops cls_route4_ops __read_mostly = { | |||
634 | .delete = route4_delete, | 642 | .delete = route4_delete, |
635 | .walk = route4_walk, | 643 | .walk = route4_walk, |
636 | .dump = route4_dump, | 644 | .dump = route4_dump, |
645 | .bind_class = route4_bind_class, | ||
637 | .owner = THIS_MODULE, | 646 | .owner = THIS_MODULE, |
638 | }; | 647 | }; |
639 | 648 | ||
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index 26203ff817f3..98c05db85bcb 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h | |||
@@ -723,6 +723,14 @@ nla_put_failure: | |||
723 | return -1; | 723 | return -1; |
724 | } | 724 | } |
725 | 725 | ||
726 | static void rsvp_bind_class(void *fh, u32 classid, unsigned long cl) | ||
727 | { | ||
728 | struct rsvp_filter *f = fh; | ||
729 | |||
730 | if (f && f->res.classid == classid) | ||
731 | f->res.class = cl; | ||
732 | } | ||
733 | |||
726 | static struct tcf_proto_ops RSVP_OPS __read_mostly = { | 734 | static struct tcf_proto_ops RSVP_OPS __read_mostly = { |
727 | .kind = RSVP_ID, | 735 | .kind = RSVP_ID, |
728 | .classify = rsvp_classify, | 736 | .classify = rsvp_classify, |
@@ -733,6 +741,7 @@ static struct tcf_proto_ops RSVP_OPS __read_mostly = { | |||
733 | .delete = rsvp_delete, | 741 | .delete = rsvp_delete, |
734 | .walk = rsvp_walk, | 742 | .walk = rsvp_walk, |
735 | .dump = rsvp_dump, | 743 | .dump = rsvp_dump, |
744 | .bind_class = rsvp_bind_class, | ||
736 | .owner = THIS_MODULE, | 745 | .owner = THIS_MODULE, |
737 | }; | 746 | }; |
738 | 747 | ||
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index fb281b9b2c52..14a7e08b2fa9 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -606,6 +606,14 @@ nla_put_failure: | |||
606 | return -1; | 606 | return -1; |
607 | } | 607 | } |
608 | 608 | ||
609 | static void tcindex_bind_class(void *fh, u32 classid, unsigned long cl) | ||
610 | { | ||
611 | struct tcindex_filter_result *r = fh; | ||
612 | |||
613 | if (r && r->res.classid == classid) | ||
614 | r->res.class = cl; | ||
615 | } | ||
616 | |||
609 | static struct tcf_proto_ops cls_tcindex_ops __read_mostly = { | 617 | static struct tcf_proto_ops cls_tcindex_ops __read_mostly = { |
610 | .kind = "tcindex", | 618 | .kind = "tcindex", |
611 | .classify = tcindex_classify, | 619 | .classify = tcindex_classify, |
@@ -616,6 +624,7 @@ static struct tcf_proto_ops cls_tcindex_ops __read_mostly = { | |||
616 | .delete = tcindex_delete, | 624 | .delete = tcindex_delete, |
617 | .walk = tcindex_walk, | 625 | .walk = tcindex_walk, |
618 | .dump = tcindex_dump, | 626 | .dump = tcindex_dump, |
627 | .bind_class = tcindex_bind_class, | ||
619 | .owner = THIS_MODULE, | 628 | .owner = THIS_MODULE, |
620 | }; | 629 | }; |
621 | 630 | ||
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 99ea4c74dd5b..10b8d851fc6b 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -1112,6 +1112,14 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg) | |||
1112 | } | 1112 | } |
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | static void u32_bind_class(void *fh, u32 classid, unsigned long cl) | ||
1116 | { | ||
1117 | struct tc_u_knode *n = fh; | ||
1118 | |||
1119 | if (n && n->res.classid == classid) | ||
1120 | n->res.class = cl; | ||
1121 | } | ||
1122 | |||
1115 | static int u32_dump(struct net *net, struct tcf_proto *tp, void *fh, | 1123 | static int u32_dump(struct net *net, struct tcf_proto *tp, void *fh, |
1116 | struct sk_buff *skb, struct tcmsg *t) | 1124 | struct sk_buff *skb, struct tcmsg *t) |
1117 | { | 1125 | { |
@@ -1242,6 +1250,7 @@ static struct tcf_proto_ops cls_u32_ops __read_mostly = { | |||
1242 | .delete = u32_delete, | 1250 | .delete = u32_delete, |
1243 | .walk = u32_walk, | 1251 | .walk = u32_walk, |
1244 | .dump = u32_dump, | 1252 | .dump = u32_dump, |
1253 | .bind_class = u32_bind_class, | ||
1245 | .owner = THIS_MODULE, | 1254 | .owner = THIS_MODULE, |
1246 | }; | 1255 | }; |
1247 | 1256 | ||
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 | } |