diff options
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r-- | net/sched/sch_api.c | 112 |
1 files changed, 72 insertions, 40 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 6cd491013b50..6d6fe16289f3 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -34,10 +34,12 @@ | |||
34 | #include <net/netlink.h> | 34 | #include <net/netlink.h> |
35 | #include <net/pkt_sched.h> | 35 | #include <net/pkt_sched.h> |
36 | 36 | ||
37 | static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid, | 37 | static int qdisc_notify(struct net *net, struct sk_buff *oskb, |
38 | struct nlmsghdr *n, u32 clid, | ||
38 | struct Qdisc *old, struct Qdisc *new); | 39 | struct Qdisc *old, struct Qdisc *new); |
39 | static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 40 | static int tclass_notify(struct net *net, struct sk_buff *oskb, |
40 | struct Qdisc *q, unsigned long cl, int event); | 41 | struct nlmsghdr *n, struct Qdisc *q, |
42 | unsigned long cl, int event); | ||
41 | 43 | ||
42 | /* | 44 | /* |
43 | 45 | ||
@@ -638,11 +640,12 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) | |||
638 | } | 640 | } |
639 | EXPORT_SYMBOL(qdisc_tree_decrease_qlen); | 641 | EXPORT_SYMBOL(qdisc_tree_decrease_qlen); |
640 | 642 | ||
641 | static void notify_and_destroy(struct sk_buff *skb, struct nlmsghdr *n, u32 clid, | 643 | static void notify_and_destroy(struct net *net, struct sk_buff *skb, |
644 | struct nlmsghdr *n, u32 clid, | ||
642 | struct Qdisc *old, struct Qdisc *new) | 645 | struct Qdisc *old, struct Qdisc *new) |
643 | { | 646 | { |
644 | if (new || old) | 647 | if (new || old) |
645 | qdisc_notify(skb, n, clid, old, new); | 648 | qdisc_notify(net, skb, n, clid, old, new); |
646 | 649 | ||
647 | if (old) | 650 | if (old) |
648 | qdisc_destroy(old); | 651 | qdisc_destroy(old); |
@@ -662,6 +665,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
662 | struct Qdisc *new, struct Qdisc *old) | 665 | struct Qdisc *new, struct Qdisc *old) |
663 | { | 666 | { |
664 | struct Qdisc *q = old; | 667 | struct Qdisc *q = old; |
668 | struct net *net = dev_net(dev); | ||
665 | int err = 0; | 669 | int err = 0; |
666 | 670 | ||
667 | if (parent == NULL) { | 671 | if (parent == NULL) { |
@@ -698,12 +702,13 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
698 | } | 702 | } |
699 | 703 | ||
700 | if (!ingress) { | 704 | if (!ingress) { |
701 | notify_and_destroy(skb, n, classid, dev->qdisc, new); | 705 | notify_and_destroy(net, skb, n, classid, |
706 | dev->qdisc, new); | ||
702 | if (new && !new->ops->attach) | 707 | if (new && !new->ops->attach) |
703 | atomic_inc(&new->refcnt); | 708 | atomic_inc(&new->refcnt); |
704 | dev->qdisc = new ? : &noop_qdisc; | 709 | dev->qdisc = new ? : &noop_qdisc; |
705 | } else { | 710 | } else { |
706 | notify_and_destroy(skb, n, classid, old, new); | 711 | notify_and_destroy(net, skb, n, classid, old, new); |
707 | } | 712 | } |
708 | 713 | ||
709 | if (dev->flags & IFF_UP) | 714 | if (dev->flags & IFF_UP) |
@@ -721,7 +726,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
721 | err = -ENOENT; | 726 | err = -ENOENT; |
722 | } | 727 | } |
723 | if (!err) | 728 | if (!err) |
724 | notify_and_destroy(skb, n, classid, old, new); | 729 | notify_and_destroy(net, skb, n, classid, old, new); |
725 | } | 730 | } |
726 | return err; | 731 | return err; |
727 | } | 732 | } |
@@ -947,10 +952,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
947 | struct Qdisc *p = NULL; | 952 | struct Qdisc *p = NULL; |
948 | int err; | 953 | int err; |
949 | 954 | ||
950 | if (!net_eq(net, &init_net)) | 955 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
951 | return -EINVAL; | ||
952 | |||
953 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | ||
954 | return -ENODEV; | 956 | return -ENODEV; |
955 | 957 | ||
956 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 958 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -990,7 +992,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
990 | if ((err = qdisc_graft(dev, p, skb, n, clid, NULL, q)) != 0) | 992 | if ((err = qdisc_graft(dev, p, skb, n, clid, NULL, q)) != 0) |
991 | return err; | 993 | return err; |
992 | } else { | 994 | } else { |
993 | qdisc_notify(skb, n, clid, NULL, q); | 995 | qdisc_notify(net, skb, n, clid, NULL, q); |
994 | } | 996 | } |
995 | return 0; | 997 | return 0; |
996 | } | 998 | } |
@@ -1009,16 +1011,13 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1009 | struct Qdisc *q, *p; | 1011 | struct Qdisc *q, *p; |
1010 | int err; | 1012 | int err; |
1011 | 1013 | ||
1012 | if (!net_eq(net, &init_net)) | ||
1013 | return -EINVAL; | ||
1014 | |||
1015 | replay: | 1014 | replay: |
1016 | /* Reinit, just in case something touches this. */ | 1015 | /* Reinit, just in case something touches this. */ |
1017 | tcm = NLMSG_DATA(n); | 1016 | tcm = NLMSG_DATA(n); |
1018 | clid = tcm->tcm_parent; | 1017 | clid = tcm->tcm_parent; |
1019 | q = p = NULL; | 1018 | q = p = NULL; |
1020 | 1019 | ||
1021 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | 1020 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
1022 | return -ENODEV; | 1021 | return -ENODEV; |
1023 | 1022 | ||
1024 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1023 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1105,7 +1104,7 @@ replay: | |||
1105 | return -EINVAL; | 1104 | return -EINVAL; |
1106 | err = qdisc_change(q, tca); | 1105 | err = qdisc_change(q, tca); |
1107 | if (err == 0) | 1106 | if (err == 0) |
1108 | qdisc_notify(skb, n, clid, NULL, q); | 1107 | qdisc_notify(net, skb, n, clid, NULL, q); |
1109 | return err; | 1108 | return err; |
1110 | 1109 | ||
1111 | create_n_graft: | 1110 | create_n_graft: |
@@ -1195,8 +1194,9 @@ nla_put_failure: | |||
1195 | return -1; | 1194 | return -1; |
1196 | } | 1195 | } |
1197 | 1196 | ||
1198 | static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 1197 | static int qdisc_notify(struct net *net, struct sk_buff *oskb, |
1199 | u32 clid, struct Qdisc *old, struct Qdisc *new) | 1198 | struct nlmsghdr *n, u32 clid, |
1199 | struct Qdisc *old, struct Qdisc *new) | ||
1200 | { | 1200 | { |
1201 | struct sk_buff *skb; | 1201 | struct sk_buff *skb; |
1202 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; | 1202 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; |
@@ -1215,7 +1215,7 @@ static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, | |||
1215 | } | 1215 | } |
1216 | 1216 | ||
1217 | if (skb->len) | 1217 | if (skb->len) |
1218 | return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 1218 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); |
1219 | 1219 | ||
1220 | err_out: | 1220 | err_out: |
1221 | kfree_skb(skb); | 1221 | kfree_skb(skb); |
@@ -1274,15 +1274,12 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) | |||
1274 | int s_idx, s_q_idx; | 1274 | int s_idx, s_q_idx; |
1275 | struct net_device *dev; | 1275 | struct net_device *dev; |
1276 | 1276 | ||
1277 | if (!net_eq(net, &init_net)) | ||
1278 | return 0; | ||
1279 | |||
1280 | s_idx = cb->args[0]; | 1277 | s_idx = cb->args[0]; |
1281 | s_q_idx = q_idx = cb->args[1]; | 1278 | s_q_idx = q_idx = cb->args[1]; |
1282 | 1279 | ||
1283 | rcu_read_lock(); | 1280 | rcu_read_lock(); |
1284 | idx = 0; | 1281 | idx = 0; |
1285 | for_each_netdev_rcu(&init_net, dev) { | 1282 | for_each_netdev_rcu(net, dev) { |
1286 | struct netdev_queue *dev_queue; | 1283 | struct netdev_queue *dev_queue; |
1287 | 1284 | ||
1288 | if (idx < s_idx) | 1285 | if (idx < s_idx) |
@@ -1334,10 +1331,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1334 | u32 qid = TC_H_MAJ(clid); | 1331 | u32 qid = TC_H_MAJ(clid); |
1335 | int err; | 1332 | int err; |
1336 | 1333 | ||
1337 | if (!net_eq(net, &init_net)) | 1334 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
1338 | return -EINVAL; | ||
1339 | |||
1340 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | ||
1341 | return -ENODEV; | 1335 | return -ENODEV; |
1342 | 1336 | ||
1343 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1337 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1418,10 +1412,10 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1418 | if (cops->delete) | 1412 | if (cops->delete) |
1419 | err = cops->delete(q, cl); | 1413 | err = cops->delete(q, cl); |
1420 | if (err == 0) | 1414 | if (err == 0) |
1421 | tclass_notify(skb, n, q, cl, RTM_DELTCLASS); | 1415 | tclass_notify(net, skb, n, q, cl, RTM_DELTCLASS); |
1422 | goto out; | 1416 | goto out; |
1423 | case RTM_GETTCLASS: | 1417 | case RTM_GETTCLASS: |
1424 | err = tclass_notify(skb, n, q, cl, RTM_NEWTCLASS); | 1418 | err = tclass_notify(net, skb, n, q, cl, RTM_NEWTCLASS); |
1425 | goto out; | 1419 | goto out; |
1426 | default: | 1420 | default: |
1427 | err = -EINVAL; | 1421 | err = -EINVAL; |
@@ -1434,7 +1428,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1434 | if (cops->change) | 1428 | if (cops->change) |
1435 | err = cops->change(q, clid, pid, tca, &new_cl); | 1429 | err = cops->change(q, clid, pid, tca, &new_cl); |
1436 | if (err == 0) | 1430 | if (err == 0) |
1437 | tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS); | 1431 | tclass_notify(net, skb, n, q, new_cl, RTM_NEWTCLASS); |
1438 | 1432 | ||
1439 | out: | 1433 | out: |
1440 | if (cl) | 1434 | if (cl) |
@@ -1486,8 +1480,9 @@ nla_put_failure: | |||
1486 | return -1; | 1480 | return -1; |
1487 | } | 1481 | } |
1488 | 1482 | ||
1489 | static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 1483 | static int tclass_notify(struct net *net, struct sk_buff *oskb, |
1490 | struct Qdisc *q, unsigned long cl, int event) | 1484 | struct nlmsghdr *n, struct Qdisc *q, |
1485 | unsigned long cl, int event) | ||
1491 | { | 1486 | { |
1492 | struct sk_buff *skb; | 1487 | struct sk_buff *skb; |
1493 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; | 1488 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; |
@@ -1501,7 +1496,7 @@ static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, | |||
1501 | return -EINVAL; | 1496 | return -EINVAL; |
1502 | } | 1497 | } |
1503 | 1498 | ||
1504 | return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 1499 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); |
1505 | } | 1500 | } |
1506 | 1501 | ||
1507 | struct qdisc_dump_args | 1502 | struct qdisc_dump_args |
@@ -1576,12 +1571,9 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
1576 | struct net_device *dev; | 1571 | struct net_device *dev; |
1577 | int t, s_t; | 1572 | int t, s_t; |
1578 | 1573 | ||
1579 | if (!net_eq(net, &init_net)) | ||
1580 | return 0; | ||
1581 | |||
1582 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) | 1574 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) |
1583 | return 0; | 1575 | return 0; |
1584 | if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | 1576 | if ((dev = dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
1585 | return 0; | 1577 | return 0; |
1586 | 1578 | ||
1587 | s_t = cb->args[0]; | 1579 | s_t = cb->args[0]; |
@@ -1701,15 +1693,55 @@ static const struct file_operations psched_fops = { | |||
1701 | .llseek = seq_lseek, | 1693 | .llseek = seq_lseek, |
1702 | .release = single_release, | 1694 | .release = single_release, |
1703 | }; | 1695 | }; |
1696 | |||
1697 | static int __net_init psched_net_init(struct net *net) | ||
1698 | { | ||
1699 | struct proc_dir_entry *e; | ||
1700 | |||
1701 | e = proc_net_fops_create(net, "psched", 0, &psched_fops); | ||
1702 | if (e == NULL) | ||
1703 | return -ENOMEM; | ||
1704 | |||
1705 | return 0; | ||
1706 | } | ||
1707 | |||
1708 | static void __net_exit psched_net_exit(struct net *net) | ||
1709 | { | ||
1710 | proc_net_remove(net, "psched"); | ||
1711 | |||
1712 | return; | ||
1713 | } | ||
1714 | #else | ||
1715 | static int __net_init psched_net_init(struct net *net) | ||
1716 | { | ||
1717 | return 0; | ||
1718 | } | ||
1719 | |||
1720 | static void __net_exit psched_net_exit(struct net *net) | ||
1721 | { | ||
1722 | } | ||
1704 | #endif | 1723 | #endif |
1705 | 1724 | ||
1725 | static struct pernet_operations psched_net_ops = { | ||
1726 | .init = psched_net_init, | ||
1727 | .exit = psched_net_exit, | ||
1728 | }; | ||
1729 | |||
1706 | static int __init pktsched_init(void) | 1730 | static int __init pktsched_init(void) |
1707 | { | 1731 | { |
1732 | int err; | ||
1733 | |||
1734 | err = register_pernet_subsys(&psched_net_ops); | ||
1735 | if (err) { | ||
1736 | printk(KERN_ERR "pktsched_init: " | ||
1737 | "cannot initialize per netns operations\n"); | ||
1738 | return err; | ||
1739 | } | ||
1740 | |||
1708 | register_qdisc(&pfifo_qdisc_ops); | 1741 | register_qdisc(&pfifo_qdisc_ops); |
1709 | register_qdisc(&bfifo_qdisc_ops); | 1742 | register_qdisc(&bfifo_qdisc_ops); |
1710 | register_qdisc(&pfifo_head_drop_qdisc_ops); | 1743 | register_qdisc(&pfifo_head_drop_qdisc_ops); |
1711 | register_qdisc(&mq_qdisc_ops); | 1744 | register_qdisc(&mq_qdisc_ops); |
1712 | proc_net_fops_create(&init_net, "psched", 0, &psched_fops); | ||
1713 | 1745 | ||
1714 | rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL); | 1746 | rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL); |
1715 | rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL); | 1747 | rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL); |