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