aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sch_generic.h1
-rw-r--r--net/sched/cls_basic.c9
-rw-r--r--net/sched/cls_bpf.c9
-rw-r--r--net/sched/cls_flower.c9
-rw-r--r--net/sched/cls_fw.c9
-rw-r--r--net/sched/cls_matchall.c9
-rw-r--r--net/sched/cls_route.c9
-rw-r--r--net/sched/cls_rsvp.h9
-rw-r--r--net/sched/cls_tcindex.c9
-rw-r--r--net/sched/cls_u32.c9
-rw-r--r--net/sched/sch_api.c68
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
238static 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
238static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh, 246static 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
610static 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
610static void cls_bpf_walk(struct tcf_proto *tp, struct tcf_walker *arg) 618static 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
640static int __init cls_bpf_init_mod(void) 649static 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
1354static 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
1354static struct tcf_proto_ops cls_fl_ops __read_mostly = { 1362static 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
415static 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
415static struct tcf_proto_ops cls_fw_ops __read_mostly = { 423static 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
254static 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
254static struct tcf_proto_ops cls_mall_ops __read_mostly = { 262static 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
627static 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
627static struct tcf_proto_ops cls_route4_ops __read_mostly = { 635static 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
726static 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
726static struct tcf_proto_ops RSVP_OPS __read_mostly = { 734static 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
609static 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
609static struct tcf_proto_ops cls_tcindex_ops __read_mostly = { 617static 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
1115static 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
1115static int u32_dump(struct net *net, struct tcf_proto *tp, void *fh, 1123static 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
1654struct tcf_bind_args {
1655 struct tcf_walker w;
1656 u32 classid;
1657 unsigned long cl;
1658};
1659
1660static 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
1672static 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
1703static void tc_bind_tclass(struct Qdisc *q, u32 portid, u32 clid,
1704 unsigned long new_cl)
1705{
1706}
1707
1708#endif
1709
1651static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, 1710static 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 }
1773out: 1837out:
1774 return err; 1838 return err;
1775} 1839}