aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r--net/sched/sch_api.c121
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
38static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid, 38static 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);
40static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, 41static 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}
640EXPORT_SYMBOL(qdisc_tree_decrease_qlen); 642EXPORT_SYMBOL(qdisc_tree_decrease_qlen);
641 643
642static void notify_and_destroy(struct sk_buff *skb, struct nlmsghdr *n, u32 clid, 644static 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
1016replay: 1015replay:
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
1112create_n_graft: 1111create_n_graft:
@@ -1196,8 +1195,9 @@ nla_put_failure:
1196 return -1; 1195 return -1;
1197} 1196}
1198 1197
1199static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, 1198static 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
1221err_out: 1221err_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
1440out: 1434out:
1441 if (cl) 1435 if (cl)
@@ -1487,8 +1481,9 @@ nla_put_failure:
1487 return -1; 1481 return -1;
1488} 1482}
1489 1483
1490static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, 1484static 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
1508struct qdisc_dump_args 1503struct 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
1693static int psched_open(struct inode *inode, struct file *file) 1688static 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
1698static const struct file_operations psched_fops = { 1693static 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
1701static 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
1712static void __net_exit psched_net_exit(struct net *net)
1713{
1714 proc_net_remove(net, "psched");
1715}
1716#else
1717static int __net_init psched_net_init(struct net *net)
1718{
1719 return 0;
1720}
1721
1722static void __net_exit psched_net_exit(struct net *net)
1723{
1724}
1705#endif 1725#endif
1706 1726
1727static struct pernet_operations psched_net_ops = {
1728 .init = psched_net_init,
1729 .exit = psched_net_exit,
1730};
1731
1707static int __init pktsched_init(void) 1732static 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);