summaryrefslogtreecommitdiff
path: root/net/sched
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 11:54:01 (GMT)
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 11:54:01 (GMT)
commit0ba6c33bcddc64a54b5f1c25a696c4767dc76292 (patch)
tree62e616f97a4762d8e75bf732e4827af2d15d52c5 /net/sched
parent21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (diff)
parent85040bcb4643cba578839e953f25e2d1965d83d0 (diff)
downloadlinux-fsl-qoriq-0ba6c33bcddc64a54b5f1c25a696c4767dc76292.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25: (1470 commits) [IPV6] ADDRLABEL: Fix double free on label deletion. [PPP]: Sparse warning fixes. [IPV4] fib_trie: remove unneeded NULL check [IPV4] fib_trie: More whitespace cleanup. [NET_SCHED]: Use nla_policy for attribute validation in ematches [NET_SCHED]: Use nla_policy for attribute validation in actions [NET_SCHED]: Use nla_policy for attribute validation in classifiers [NET_SCHED]: Use nla_policy for attribute validation in packet schedulers [NET_SCHED]: sch_api: introduce constant for rate table size [NET_SCHED]: Use typeful attribute parsing helpers [NET_SCHED]: Use typeful attribute construction helpers [NET_SCHED]: Use NLA_PUT_STRING for string dumping [NET_SCHED]: Use nla_nest_start/nla_nest_end [NET_SCHED]: Propagate nla_parse return value [NET_SCHED]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get [NET_SCHED]: act_api: use nlmsg_parse [NET_SCHED]: act_api: fix netlink API conversion bug [NET_SCHED]: sch_netem: use nla_parse_nested_compat [NET_SCHED]: sch_atm: fix format string warning [NETNS]: Add namespace for ICMP replying code. ...
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/Kconfig11
-rw-r--r--net/sched/act_api.c340
-rw-r--r--net/sched/act_gact.c40
-rw-r--r--net/sched/act_ipt.c55
-rw-r--r--net/sched/act_mirred.c27
-rw-r--r--net/sched/act_nat.c39
-rw-r--r--net/sched/act_pedit.c29
-rw-r--r--net/sched/act_police.c67
-rw-r--r--net/sched/act_simple.c33
-rw-r--r--net/sched/cls_api.c189
-rw-r--r--net/sched/cls_basic.c57
-rw-r--r--net/sched/cls_fw.c68
-rw-r--r--net/sched/cls_route.c84
-rw-r--r--net/sched/cls_rsvp.h69
-rw-r--r--net/sched/cls_tcindex.c141
-rw-r--r--net/sched/cls_u32.c103
-rw-r--r--net/sched/em_meta.c64
-rw-r--r--net/sched/em_text.c9
-rw-r--r--net/sched/ematch.c98
-rw-r--r--net/sched/sch_api.c134
-rw-r--r--net/sched/sch_atm.c208
-rw-r--r--net/sched/sch_blackhole.c2
-rw-r--r--net/sched/sch_cbq.c183
-rw-r--r--net/sched/sch_dsmark.c276
-rw-r--r--net/sched/sch_fifo.c17
-rw-r--r--net/sched/sch_generic.c46
-rw-r--r--net/sched/sch_gred.c77
-rw-r--r--net/sched/sch_hfsc.c92
-rw-r--r--net/sched/sch_htb.c112
-rw-r--r--net/sched/sch_ingress.c292
-rw-r--r--net/sched/sch_netem.c143
-rw-r--r--net/sched/sch_prio.c41
-rw-r--r--net/sched/sch_red.c64
-rw-r--r--net/sched/sch_sfq.c66
-rw-r--r--net/sched/sch_tbf.c68
-rw-r--r--net/sched/sch_teql.c2
36 files changed, 1682 insertions, 1664 deletions
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 9c15c488..87af7c9 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -198,6 +198,7 @@ config NET_SCH_NETEM
config NET_SCH_INGRESS
tristate "Ingress Qdisc"
+ depends on NET_CLS_ACT || NETFILTER
---help---
Say Y here if you want to use classifiers for incoming packets.
If unsure, say Y.
@@ -445,7 +446,6 @@ config NET_ACT_IPT
config NET_ACT_NAT
tristate "Stateless NAT"
depends on NET_CLS_ACT
- select NETFILTER
---help---
Say Y here to do stateless NAT on IPv4 packets. You should use
netfilter for NAT unless you know what you are doing.
@@ -476,15 +476,6 @@ config NET_ACT_SIMP
To compile this code as a module, choose M here: the
module will be called simple.
-config NET_CLS_POLICE
- bool "Traffic Policing (obsolete)"
- select NET_CLS_ACT
- select NET_ACT_POLICE
- ---help---
- Say Y here if you want to do traffic policing, i.e. strict
- bandwidth limiting. This option is obsolete and just selects
- the option replacing it. It will be removed in the future.
-
config NET_CLS_IND
bool "Incoming device classification"
depends on NET_CLS_U32 || NET_CLS_FW
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 72cdb0f..0b8eb23 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -18,6 +18,9 @@
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/kmod.h>
+#include <linux/err.h>
+#include <net/net_namespace.h>
+#include <net/sock.h>
#include <net/sch_generic.h>
#include <net/act_api.h>
#include <net/netlink.h>
@@ -66,7 +69,7 @@ static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
{
struct tcf_common *p;
int err = 0, index = -1,i = 0, s_i = 0, n_i = 0;
- struct rtattr *r ;
+ struct nlattr *nest;
read_lock_bh(hinfo->lock);
@@ -81,15 +84,17 @@ static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
continue;
a->priv = p;
a->order = n_i;
- r = (struct rtattr *)skb_tail_pointer(skb);
- RTA_PUT(skb, a->order, 0, NULL);
+
+ nest = nla_nest_start(skb, a->order);
+ if (nest == NULL)
+ goto nla_put_failure;
err = tcf_action_dump_1(skb, a, 0, 0);
if (err < 0) {
index--;
- nlmsg_trim(skb, r);
+ nlmsg_trim(skb, nest);
goto done;
}
- r->rta_len = skb_tail_pointer(skb) - (u8 *)r;
+ nla_nest_end(skb, nest);
n_i++;
if (n_i >= TCA_ACT_MAX_PRIO)
goto done;
@@ -101,8 +106,8 @@ done:
cb->args[0] += n_i;
return n_i;
-rtattr_failure:
- nlmsg_trim(skb, r);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
goto done;
}
@@ -110,12 +115,13 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a,
struct tcf_hashinfo *hinfo)
{
struct tcf_common *p, *s_p;
- struct rtattr *r ;
+ struct nlattr *nest;
int i= 0, n_i = 0;
- r = (struct rtattr *)skb_tail_pointer(skb);
- RTA_PUT(skb, a->order, 0, NULL);
- RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
+ nest = nla_nest_start(skb, a->order);
+ if (nest == NULL)
+ goto nla_put_failure;
+ NLA_PUT_STRING(skb, TCA_KIND, a->ops->kind);
for (i = 0; i < (hinfo->hmask + 1); i++) {
p = hinfo->htab[tcf_hash(i, hinfo->hmask)];
@@ -127,12 +133,12 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a,
p = s_p;
}
}
- RTA_PUT(skb, TCA_FCNT, 4, &n_i);
- r->rta_len = skb_tail_pointer(skb) - (u8 *)r;
+ NLA_PUT_U32(skb, TCA_FCNT, n_i);
+ nla_nest_end(skb, nest);
return n_i;
-rtattr_failure:
- nlmsg_trim(skb, r);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
return -EINVAL;
}
@@ -209,7 +215,7 @@ struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind,
}
EXPORT_SYMBOL(tcf_hash_check);
-struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est, struct tc_action *a, int size, int bind, u32 *idx_gen, struct tcf_hashinfo *hinfo)
+struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a, int size, int bind, u32 *idx_gen, struct tcf_hashinfo *hinfo)
{
struct tcf_common *p = kzalloc(size, GFP_KERNEL);
@@ -261,6 +267,7 @@ int tcf_register_action(struct tc_action_ops *act)
write_unlock(&act_mod_lock);
return 0;
}
+EXPORT_SYMBOL(tcf_register_action);
int tcf_unregister_action(struct tc_action_ops *act)
{
@@ -279,6 +286,7 @@ int tcf_unregister_action(struct tc_action_ops *act)
write_unlock(&act_mod_lock);
return err;
}
+EXPORT_SYMBOL(tcf_unregister_action);
/* lookup by name */
static struct tc_action_ops *tc_lookup_action_n(char *kind)
@@ -301,15 +309,15 @@ static struct tc_action_ops *tc_lookup_action_n(char *kind)
return a;
}
-/* lookup by rtattr */
-static struct tc_action_ops *tc_lookup_action(struct rtattr *kind)
+/* lookup by nlattr */
+static struct tc_action_ops *tc_lookup_action(struct nlattr *kind)
{
struct tc_action_ops *a = NULL;
if (kind) {
read_lock(&act_mod_lock);
for (a = act_base; a; a = a->next) {
- if (rtattr_strcmp(kind, a->kind) == 0) {
+ if (nla_strcmp(kind, a->kind) == 0) {
if (!try_module_get(a->owner)) {
read_unlock(&act_mod_lock);
return NULL;
@@ -375,6 +383,7 @@ repeat:
exec_done:
return ret;
}
+EXPORT_SYMBOL(tcf_action_exec);
void tcf_action_destroy(struct tc_action *act, int bind)
{
@@ -409,73 +418,77 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
int err = -EINVAL;
unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *r;
+ struct nlattr *nest;
if (a->ops == NULL || a->ops->dump == NULL)
return err;
- RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
+ NLA_PUT_STRING(skb, TCA_KIND, a->ops->kind);
if (tcf_action_copy_stats(skb, a, 0))
- goto rtattr_failure;
- r = (struct rtattr *)skb_tail_pointer(skb);
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ goto nla_put_failure;
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
if ((err = tcf_action_dump_old(skb, a, bind, ref)) > 0) {
- r->rta_len = skb_tail_pointer(skb) - (u8 *)r;
+ nla_nest_end(skb, nest);
return err;
}
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
+EXPORT_SYMBOL(tcf_action_dump_1);
int
tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref)
{
struct tc_action *a;
int err = -EINVAL;
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *r ;
+ struct nlattr *nest;
while ((a = act) != NULL) {
- r = (struct rtattr *)skb_tail_pointer(skb);
act = a->next;
- RTA_PUT(skb, a->order, 0, NULL);
+ nest = nla_nest_start(skb, a->order);
+ if (nest == NULL)
+ goto nla_put_failure;
err = tcf_action_dump_1(skb, a, bind, ref);
if (err < 0)
goto errout;
- r->rta_len = skb_tail_pointer(skb) - (u8 *)r;
+ nla_nest_end(skb, nest);
}
return 0;
-rtattr_failure:
+nla_put_failure:
err = -EINVAL;
errout:
- nlmsg_trim(skb, b);
+ nla_nest_cancel(skb, nest);
return err;
}
-struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
- char *name, int ovr, int bind, int *err)
+struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est,
+ char *name, int ovr, int bind)
{
struct tc_action *a;
struct tc_action_ops *a_o;
char act_name[IFNAMSIZ];
- struct rtattr *tb[TCA_ACT_MAX+1];
- struct rtattr *kind;
-
- *err = -EINVAL;
+ struct nlattr *tb[TCA_ACT_MAX+1];
+ struct nlattr *kind;
+ int err;
if (name == NULL) {
- if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0)
+ err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL);
+ if (err < 0)
goto err_out;
- kind = tb[TCA_ACT_KIND-1];
+ err = -EINVAL;
+ kind = tb[TCA_ACT_KIND];
if (kind == NULL)
goto err_out;
- if (rtattr_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
+ if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
goto err_out;
} else {
+ err = -EINVAL;
if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
goto err_out;
}
@@ -496,36 +509,35 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
* indicate this using -EAGAIN.
*/
if (a_o != NULL) {
- *err = -EAGAIN;
+ err = -EAGAIN;
goto err_mod;
}
#endif
- *err = -ENOENT;
+ err = -ENOENT;
goto err_out;
}
- *err = -ENOMEM;
+ err = -ENOMEM;
a = kzalloc(sizeof(*a), GFP_KERNEL);
if (a == NULL)
goto err_mod;
/* backward compatibility for policer */
if (name == NULL)
- *err = a_o->init(tb[TCA_ACT_OPTIONS-1], est, a, ovr, bind);
+ err = a_o->init(tb[TCA_ACT_OPTIONS], est, a, ovr, bind);
else
- *err = a_o->init(rta, est, a, ovr, bind);
- if (*err < 0)
+ err = a_o->init(nla, est, a, ovr, bind);
+ if (err < 0)
goto err_free;
/* module count goes up only when brand new policy is created
if it exists and is only bound to in a_o->init() then
ACT_P_CREATED is not returned (a zero is).
*/
- if (*err != ACT_P_CREATED)
+ if (err != ACT_P_CREATED)
module_put(a_o->owner);
a->ops = a_o;
- *err = 0;
return a;
err_free:
@@ -533,26 +545,26 @@ err_free:
err_mod:
module_put(a_o->owner);
err_out:
- return NULL;
+ return ERR_PTR(err);
}
-struct tc_action *tcf_action_init(struct rtattr *rta, struct rtattr *est,
- char *name, int ovr, int bind, int *err)
+struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est,
+ char *name, int ovr, int bind)
{
- struct rtattr *tb[TCA_ACT_MAX_PRIO+1];
+ struct nlattr *tb[TCA_ACT_MAX_PRIO+1];
struct tc_action *head = NULL, *act, *act_prev = NULL;
+ int err;
int i;
- if (rtattr_parse_nested(tb, TCA_ACT_MAX_PRIO, rta) < 0) {
- *err = -EINVAL;
- return head;
- }
+ err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL);
+ if (err < 0)
+ return ERR_PTR(err);
- for (i=0; i < TCA_ACT_MAX_PRIO && tb[i]; i++) {
- act = tcf_action_init_1(tb[i], est, name, ovr, bind, err);
- if (act == NULL)
+ for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
+ act = tcf_action_init_1(tb[i], est, name, ovr, bind);
+ if (IS_ERR(act))
goto err;
- act->order = i+1;
+ act->order = i;
if (head == NULL)
head = act;
@@ -565,7 +577,7 @@ struct tc_action *tcf_action_init(struct rtattr *rta, struct rtattr *est,
err:
if (head != NULL)
tcf_action_destroy(head, bind);
- return NULL;
+ return act;
}
int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
@@ -619,7 +631,7 @@ tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq,
struct tcamsg *t;
struct nlmsghdr *nlh;
unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *x;
+ struct nlattr *nest;
nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags);
@@ -628,18 +640,19 @@ tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq,
t->tca__pad1 = 0;
t->tca__pad2 = 0;
- x = (struct rtattr *)skb_tail_pointer(skb);
- RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+ nest = nla_nest_start(skb, TCA_ACT_TAB);
+ if (nest == NULL)
+ goto nla_put_failure;
if (tcf_action_dump(skb, a, bind, ref) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
- x->rta_len = skb_tail_pointer(skb) - (u8 *)x;
+ nla_nest_end(skb, nest);
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_failure:
nlmsg_trim(skb, b);
return -1;
@@ -658,48 +671,51 @@ act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event)
return -EINVAL;
}
- return rtnl_unicast(skb, pid);
+ return rtnl_unicast(skb, &init_net, pid);
}
static struct tc_action *
-tcf_action_get_1(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int *err)
+tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
{
- struct rtattr *tb[TCA_ACT_MAX+1];
+ struct nlattr *tb[TCA_ACT_MAX+1];
struct tc_action *a;
int index;
+ int err;
- *err = -EINVAL;
- if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0)
- return NULL;
+ err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL);
+ if (err < 0)
+ goto err_out;
- if (tb[TCA_ACT_INDEX - 1] == NULL ||
- RTA_PAYLOAD(tb[TCA_ACT_INDEX - 1]) < sizeof(index))
- return NULL;
- index = *(int *)RTA_DATA(tb[TCA_ACT_INDEX - 1]);
+ err = -EINVAL;
+ if (tb[TCA_ACT_INDEX] == NULL ||
+ nla_len(tb[TCA_ACT_INDEX]) < sizeof(index))
+ goto err_out;
+ index = nla_get_u32(tb[TCA_ACT_INDEX]);
- *err = -ENOMEM;
+ err = -ENOMEM;
a = kzalloc(sizeof(struct tc_action), GFP_KERNEL);
if (a == NULL)
- return NULL;
+ goto err_out;
- *err = -EINVAL;
- a->ops = tc_lookup_action(tb[TCA_ACT_KIND - 1]);
+ err = -EINVAL;
+ a->ops = tc_lookup_action(tb[TCA_ACT_KIND]);
if (a->ops == NULL)
goto err_free;
if (a->ops->lookup == NULL)
goto err_mod;
- *err = -ENOENT;
+ err = -ENOENT;
if (a->ops->lookup(a, index) == 0)
goto err_mod;
module_put(a->ops->owner);
- *err = 0;
return a;
+
err_mod:
module_put(a->ops->owner);
err_free:
kfree(a);
- return NULL;
+err_out:
+ return ERR_PTR(err);
}
static void cleanup_a(struct tc_action *act)
@@ -725,16 +741,16 @@ static struct tc_action *create_a(int i)
return act;
}
-static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
+static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
{
struct sk_buff *skb;
unsigned char *b;
struct nlmsghdr *nlh;
struct tcamsg *t;
struct netlink_callback dcb;
- struct rtattr *x;
- struct rtattr *tb[TCA_ACT_MAX+1];
- struct rtattr *kind;
+ struct nlattr *nest;
+ struct nlattr *tb[TCA_ACT_MAX+1];
+ struct nlattr *kind;
struct tc_action *a = create_a(0);
int err = -EINVAL;
@@ -752,10 +768,12 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
b = skb_tail_pointer(skb);
- if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0)
+ err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL);
+ if (err < 0)
goto err_out;
- kind = tb[TCA_ACT_KIND-1];
+ err = -EINVAL;
+ kind = tb[TCA_ACT_KIND];
a->ops = tc_lookup_action(kind);
if (a->ops == NULL)
goto err_out;
@@ -766,26 +784,27 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
t->tca__pad1 = 0;
t->tca__pad2 = 0;
- x = (struct rtattr *)skb_tail_pointer(skb);
- RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+ nest = nla_nest_start(skb, TCA_ACT_TAB);
+ if (nest == NULL)
+ goto nla_put_failure;
err = a->ops->walk(skb, &dcb, RTM_DELACTION, a);
if (err < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
- x->rta_len = skb_tail_pointer(skb) - (u8 *)x;
+ nla_nest_end(skb, nest);
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
nlh->nlmsg_flags |= NLM_F_ROOT;
module_put(a->ops->owner);
kfree(a);
- err = rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
if (err > 0)
return 0;
return err;
-rtattr_failure:
+nla_put_failure:
nlmsg_failure:
module_put(a->ops->owner);
err_out:
@@ -795,25 +814,28 @@ err_out:
}
static int
-tca_action_gd(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int event)
+tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event)
{
- int i, ret = 0;
- struct rtattr *tb[TCA_ACT_MAX_PRIO+1];
+ int i, ret;
+ struct nlattr *tb[TCA_ACT_MAX_PRIO+1];
struct tc_action *head = NULL, *act, *act_prev = NULL;
- if (rtattr_parse_nested(tb, TCA_ACT_MAX_PRIO, rta) < 0)
- return -EINVAL;
+ ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL);
+ if (ret < 0)
+ return ret;
if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) {
if (tb[0] != NULL && tb[1] == NULL)
return tca_action_flush(tb[0], n, pid);
}
- for (i=0; i < TCA_ACT_MAX_PRIO && tb[i]; i++) {
- act = tcf_action_get_1(tb[i], n, pid, &ret);
- if (act == NULL)
+ for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
+ act = tcf_action_get_1(tb[i], n, pid);
+ if (IS_ERR(act)) {
+ ret = PTR_ERR(act);
goto err;
- act->order = i+1;
+ }
+ act->order = i;
if (head == NULL)
head = act;
@@ -842,7 +864,7 @@ tca_action_gd(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int event)
/* now do the delete */
tcf_action_destroy(head, 0);
- ret = rtnetlink_send(skb, pid, RTNLGRP_TC,
+ ret = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC,
n->nlmsg_flags&NLM_F_ECHO);
if (ret > 0)
return 0;
@@ -859,7 +881,7 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
struct tcamsg *t;
struct nlmsghdr *nlh;
struct sk_buff *skb;
- struct rtattr *x;
+ struct nlattr *nest;
unsigned char *b;
int err = 0;
@@ -875,23 +897,24 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
t->tca__pad1 = 0;
t->tca__pad2 = 0;
- x = (struct rtattr *)skb_tail_pointer(skb);
- RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+ nest = nla_nest_start(skb, TCA_ACT_TAB);
+ if (nest == NULL)
+ goto nla_put_failure;
if (tcf_action_dump(skb, a, 0, 0) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
- x->rta_len = skb_tail_pointer(skb) - (u8 *)x;
+ nla_nest_end(skb, nest);
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
NETLINK_CB(skb).dst_group = RTNLGRP_TC;
- err = rtnetlink_send(skb, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
+ err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
if (err > 0)
err = 0;
return err;
-rtattr_failure:
+nla_put_failure:
nlmsg_failure:
kfree_skb(skb);
return -1;
@@ -899,16 +922,20 @@ nlmsg_failure:
static int
-tcf_action_add(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int ovr)
+tcf_action_add(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int ovr)
{
int ret = 0;
struct tc_action *act;
struct tc_action *a;
u32 seq = n->nlmsg_seq;
- act = tcf_action_init(rta, NULL, NULL, ovr, 0, &ret);
+ act = tcf_action_init(nla, NULL, NULL, ovr, 0);
if (act == NULL)
goto done;
+ if (IS_ERR(act)) {
+ ret = PTR_ERR(act);
+ goto done;
+ }
/* dump then free all the actions after update; inserted policy
* stays intact
@@ -924,11 +951,19 @@ done:
static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
- struct rtattr **tca = arg;
+ struct net *net = skb->sk->sk_net;
+ struct nlattr *tca[TCA_ACT_MAX + 1];
u32 pid = skb ? NETLINK_CB(skb).pid : 0;
int ret = 0, ovr = 0;
- if (tca[TCA_ACT_TAB-1] == NULL) {
+ if (net != &init_net)
+ return -EINVAL;
+
+ ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ACT_MAX, NULL);
+ if (ret < 0)
+ return ret;
+
+ if (tca[TCA_ACT_TAB] == NULL) {
printk("tc_ctl_action: received NO action attribs\n");
return -EINVAL;
}
@@ -946,15 +981,15 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
if (n->nlmsg_flags&NLM_F_REPLACE)
ovr = 1;
replay:
- ret = tcf_action_add(tca[TCA_ACT_TAB-1], n, pid, ovr);
+ ret = tcf_action_add(tca[TCA_ACT_TAB], n, pid, ovr);
if (ret == -EAGAIN)
goto replay;
break;
case RTM_DELACTION:
- ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid, RTM_DELACTION);
+ ret = tca_action_gd(tca[TCA_ACT_TAB], n, pid, RTM_DELACTION);
break;
case RTM_GETACTION:
- ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid, RTM_GETACTION);
+ ret = tca_action_gd(tca[TCA_ACT_TAB], n, pid, RTM_GETACTION);
break;
default:
BUG();
@@ -963,33 +998,30 @@ replay:
return ret;
}
-static struct rtattr *
+static struct nlattr *
find_dump_kind(struct nlmsghdr *n)
{
- struct rtattr *tb1, *tb2[TCA_ACT_MAX+1];
- struct rtattr *tb[TCA_ACT_MAX_PRIO + 1];
- struct rtattr *rta[TCAA_MAX + 1];
- struct rtattr *kind;
- int min_len = NLMSG_LENGTH(sizeof(struct tcamsg));
- int attrlen = n->nlmsg_len - NLMSG_ALIGN(min_len);
- struct rtattr *attr = (void *) n + NLMSG_ALIGN(min_len);
-
- if (rtattr_parse(rta, TCAA_MAX, attr, attrlen) < 0)
+ struct nlattr *tb1, *tb2[TCA_ACT_MAX+1];
+ struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
+ struct nlattr *nla[TCAA_MAX + 1];
+ struct nlattr *kind;
+
+ if (nlmsg_parse(n, sizeof(struct tcamsg), nla, TCAA_MAX, NULL) < 0)
return NULL;
- tb1 = rta[TCA_ACT_TAB - 1];
+ tb1 = nla[TCA_ACT_TAB];
if (tb1 == NULL)
return NULL;
- if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(tb1),
- NLMSG_ALIGN(RTA_PAYLOAD(tb1))) < 0)
- return NULL;
- if (tb[0] == NULL)
+ if (nla_parse(tb, TCA_ACT_MAX_PRIO, nla_data(tb1),
+ NLMSG_ALIGN(nla_len(tb1)), NULL) < 0)
return NULL;
- if (rtattr_parse(tb2, TCA_ACT_MAX, RTA_DATA(tb[0]),
- RTA_PAYLOAD(tb[0])) < 0)
+ if (tb[1] == NULL)
return NULL;
- kind = tb2[TCA_ACT_KIND-1];
+ if (nla_parse(tb2, TCA_ACT_MAX, nla_data(tb[1]),
+ nla_len(tb[1]), NULL) < 0)
+ return NULL;
+ kind = tb2[TCA_ACT_KIND];
return kind;
}
@@ -997,14 +1029,18 @@ find_dump_kind(struct nlmsghdr *n)
static int
tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct net *net = skb->sk->sk_net;
struct nlmsghdr *nlh;
unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *x;
+ struct nlattr *nest;
struct tc_action_ops *a_o;
struct tc_action a;
int ret = 0;
struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh);
- struct rtattr *kind = find_dump_kind(cb->nlh);
+ struct nlattr *kind = find_dump_kind(cb->nlh);
+
+ if (net != &init_net)
+ return 0;
if (kind == NULL) {
printk("tc_dump_action: action bad kind\n");
@@ -1021,7 +1057,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
if (a_o->walk == NULL) {
printk("tc_dump_action: %s !capable of dumping table\n", a_o->kind);
- goto rtattr_failure;
+ goto nla_put_failure;
}
nlh = NLMSG_PUT(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
@@ -1031,18 +1067,19 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
t->tca__pad1 = 0;
t->tca__pad2 = 0;
- x = (struct rtattr *)skb_tail_pointer(skb);
- RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+ nest = nla_nest_start(skb, TCA_ACT_TAB);
+ if (nest == NULL)
+ goto nla_put_failure;
ret = a_o->walk(skb, cb, RTM_GETACTION, &a);
if (ret < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
if (ret > 0) {
- x->rta_len = skb_tail_pointer(skb) - (u8 *)x;
+ nla_nest_end(skb, nest);
ret = skb->len;
} else
- nlmsg_trim(skb, x);
+ nla_nest_cancel(skb, nest);
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
if (NETLINK_CB(cb->skb).pid && ret)
@@ -1050,7 +1087,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
module_put(a_o->owner);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_failure:
module_put(a_o->owner);
nlmsg_trim(skb, b);
@@ -1067,8 +1104,3 @@ static int __init tc_action_init(void)
}
subsys_initcall(tc_action_init);
-
-EXPORT_SYMBOL(tcf_register_action);
-EXPORT_SYMBOL(tcf_unregister_action);
-EXPORT_SYMBOL(tcf_action_exec);
-EXPORT_SYMBOL(tcf_action_dump_1);
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index a9631e4..422872c 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -53,28 +53,34 @@ typedef int (*g_rand)(struct tcf_gact *gact);
static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ };
#endif /* CONFIG_GACT_PROB */
-static int tcf_gact_init(struct rtattr *rta, struct rtattr *est,
+static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
+ [TCA_GACT_PARMS] = { .len = sizeof(struct tc_gact) },
+ [TCA_GACT_PROB] = { .len = sizeof(struct tc_gact_p) },
+};
+
+static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
- struct rtattr *tb[TCA_GACT_MAX];
+ struct nlattr *tb[TCA_GACT_MAX + 1];
struct tc_gact *parm;
struct tcf_gact *gact;
struct tcf_common *pc;
int ret = 0;
+ int err;
- if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0)
+ if (nla == NULL)
return -EINVAL;
- if (tb[TCA_GACT_PARMS - 1] == NULL ||
- RTA_PAYLOAD(tb[TCA_GACT_PARMS - 1]) < sizeof(*parm))
+ err = nla_parse_nested(tb, TCA_GACT_MAX, nla, gact_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_GACT_PARMS] == NULL)
return -EINVAL;
- parm = RTA_DATA(tb[TCA_GACT_PARMS - 1]);
+ parm = nla_data(tb[TCA_GACT_PARMS]);
- if (tb[TCA_GACT_PROB-1] != NULL)
-#ifdef CONFIG_GACT_PROB
- if (RTA_PAYLOAD(tb[TCA_GACT_PROB-1]) < sizeof(struct tc_gact_p))
- return -EINVAL;
-#else
+#ifndef CONFIG_GACT_PROB
+ if (tb[TCA_GACT_PROB] != NULL)
return -EOPNOTSUPP;
#endif
@@ -97,8 +103,8 @@ static int tcf_gact_init(struct rtattr *rta, struct rtattr *est,
spin_lock_bh(&gact->tcf_lock);
gact->tcf_action = parm->action;
#ifdef CONFIG_GACT_PROB
- if (tb[TCA_GACT_PROB-1] != NULL) {
- struct tc_gact_p *p_parm = RTA_DATA(tb[TCA_GACT_PROB-1]);
+ if (tb[TCA_GACT_PROB] != NULL) {
+ struct tc_gact_p *p_parm = nla_data(tb[TCA_GACT_PROB]);
gact->tcfg_paction = p_parm->paction;
gact->tcfg_pval = p_parm->pval;
gact->tcfg_ptype = p_parm->ptype;
@@ -154,23 +160,23 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int
opt.refcnt = gact->tcf_refcnt - ref;
opt.bindcnt = gact->tcf_bindcnt - bind;
opt.action = gact->tcf_action;
- RTA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt);
#ifdef CONFIG_GACT_PROB
if (gact->tcfg_ptype) {
struct tc_gact_p p_opt;
p_opt.paction = gact->tcfg_paction;
p_opt.pval = gact->tcfg_pval;
p_opt.ptype = gact->tcfg_ptype;
- RTA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt);
+ NLA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt);
}
#endif
t.install = jiffies_to_clock_t(jiffies - gact->tcf_tm.install);
t.lastuse = jiffies_to_clock_t(jiffies - gact->tcf_tm.lastuse);
t.expires = jiffies_to_clock_t(gact->tcf_tm.expires);
- RTA_PUT(skb, TCA_GACT_TM, sizeof(t), &t);
+ NLA_PUT(skb, TCA_GACT_TM, sizeof(t), &t);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index fa006e0..da696fd 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -92,10 +92,17 @@ static int tcf_ipt_release(struct tcf_ipt *ipt, int bind)
return ret;
}
-static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est,
+static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
+ [TCA_IPT_TABLE] = { .type = NLA_STRING, .len = IFNAMSIZ },
+ [TCA_IPT_HOOK] = { .type = NLA_U32 },
+ [TCA_IPT_INDEX] = { .type = NLA_U32 },
+ [TCA_IPT_TARG] = { .len = sizeof(struct ipt_entry_target) },
+};
+
+static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
- struct rtattr *tb[TCA_IPT_MAX];
+ struct nlattr *tb[TCA_IPT_MAX + 1];
struct tcf_ipt *ipt;
struct tcf_common *pc;
struct ipt_entry_target *td, *t;
@@ -104,22 +111,24 @@ static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est,
u32 hook = 0;
u32 index = 0;
- if (rta == NULL || rtattr_parse_nested(tb, TCA_IPT_MAX, rta) < 0)
+ if (nla == NULL)
return -EINVAL;
- if (tb[TCA_IPT_HOOK-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_IPT_HOOK-1]) < sizeof(u32))
+ err = nla_parse_nested(tb, TCA_IPT_MAX, nla, ipt_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_IPT_HOOK] == NULL)
return -EINVAL;
- if (tb[TCA_IPT_TARG-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < sizeof(*t))
+ if (tb[TCA_IPT_TARG] == NULL)
return -EINVAL;
- td = (struct ipt_entry_target *)RTA_DATA(tb[TCA_IPT_TARG-1]);
- if (RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < td->u.target_size)
+
+ td = (struct ipt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
+ if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size)
return -EINVAL;
- if (tb[TCA_IPT_INDEX-1] != NULL &&
- RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32))
- index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]);
+ if (tb[TCA_IPT_INDEX] != NULL)
+ index = nla_get_u32(tb[TCA_IPT_INDEX]);
pc = tcf_hash_check(index, a, bind, &ipt_hash_info);
if (!pc) {
@@ -136,14 +145,14 @@ static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est,
}
ipt = to_ipt(pc);
- hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]);
+ hook = nla_get_u32(tb[TCA_IPT_HOOK]);
err = -ENOMEM;
tname = kmalloc(IFNAMSIZ, GFP_KERNEL);
if (unlikely(!tname))
goto err1;
- if (tb[TCA_IPT_TABLE - 1] == NULL ||
- rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ)
+ if (tb[TCA_IPT_TABLE] == NULL ||
+ nla_strlcpy(tname, tb[TCA_IPT_TABLE], IFNAMSIZ) >= IFNAMSIZ)
strcpy(tname, "mangle");
t = kmemdup(td, td->u.target_size, GFP_KERNEL);
@@ -243,25 +252,25 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int
t = kmemdup(ipt->tcfi_t, ipt->tcfi_t->u.user.target_size, GFP_ATOMIC);
if (unlikely(!t))
- goto rtattr_failure;
+ goto nla_put_failure;
c.bindcnt = ipt->tcf_bindcnt - bind;
c.refcnt = ipt->tcf_refcnt - ref;
strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name);
- RTA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t);
- RTA_PUT(skb, TCA_IPT_INDEX, 4, &ipt->tcf_index);
- RTA_PUT(skb, TCA_IPT_HOOK, 4, &ipt->tcfi_hook);
- RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c);
- RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, ipt->tcfi_tname);
+ NLA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t);
+ NLA_PUT_U32(skb, TCA_IPT_INDEX, ipt->tcf_index);
+ NLA_PUT_U32(skb, TCA_IPT_HOOK, ipt->tcfi_hook);
+ NLA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c);
+ NLA_PUT_STRING(skb, TCA_IPT_TABLE, ipt->tcfi_tname);
tm.install = jiffies_to_clock_t(jiffies - ipt->tcf_tm.install);
tm.lastuse = jiffies_to_clock_t(jiffies - ipt->tcf_tm.lastuse);
tm.expires = jiffies_to_clock_t(ipt->tcf_tm.expires);
- RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm);
+ NLA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm);
kfree(t);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
kfree(t);
return -1;
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index c3fde91..1aff005 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -54,24 +54,31 @@ static inline int tcf_mirred_release(struct tcf_mirred *m, int bind)
return 0;
}
-static int tcf_mirred_init(struct rtattr *rta, struct rtattr *est,
+static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
+ [TCA_MIRRED_PARMS] = { .len = sizeof(struct tc_mirred) },
+};
+
+static int tcf_mirred_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
- struct rtattr *tb[TCA_MIRRED_MAX];
+ struct nlattr *tb[TCA_MIRRED_MAX + 1];
struct tc_mirred *parm;
struct tcf_mirred *m;
struct tcf_common *pc;
struct net_device *dev = NULL;
- int ret = 0;
+ int ret = 0, err;
int ok_push = 0;
- if (rta == NULL || rtattr_parse_nested(tb, TCA_MIRRED_MAX, rta) < 0)
+ if (nla == NULL)
return -EINVAL;
- if (tb[TCA_MIRRED_PARMS-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_MIRRED_PARMS-1]) < sizeof(*parm))
+ err = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_MIRRED_PARMS] == NULL)
return -EINVAL;
- parm = RTA_DATA(tb[TCA_MIRRED_PARMS-1]);
+ parm = nla_data(tb[TCA_MIRRED_PARMS]);
if (parm->ifindex) {
dev = __dev_get_by_index(&init_net, parm->ifindex);
@@ -207,14 +214,14 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, i
opt.bindcnt = m->tcf_bindcnt - bind;
opt.eaction = m->tcfm_eaction;
opt.ifindex = m->tcfm_ifindex;
- RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt);
t.install = jiffies_to_clock_t(jiffies - m->tcf_tm.install);
t.lastuse = jiffies_to_clock_t(jiffies - m->tcf_tm.lastuse);
t.expires = jiffies_to_clock_t(m->tcf_tm.expires);
- RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t);
+ NLA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index c96273b..0a3c833 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -40,22 +40,29 @@ static struct tcf_hashinfo nat_hash_info = {
.lock = &nat_lock,
};
-static int tcf_nat_init(struct rtattr *rta, struct rtattr *est,
+static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
+ [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) },
+};
+
+static int tcf_nat_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
- struct rtattr *tb[TCA_NAT_MAX];
+ struct nlattr *tb[TCA_NAT_MAX + 1];
struct tc_nat *parm;
- int ret = 0;
+ int ret = 0, err;
struct tcf_nat *p;
struct tcf_common *pc;
- if (rta == NULL || rtattr_parse_nested(tb, TCA_NAT_MAX, rta) < 0)
+ if (nla == NULL)
return -EINVAL;
- if (tb[TCA_NAT_PARMS - 1] == NULL ||
- RTA_PAYLOAD(tb[TCA_NAT_PARMS - 1]) < sizeof(*parm))
+ err = nla_parse_nested(tb, TCA_NAT_MAX, nla, nat_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_NAT_PARMS] == NULL)
return -EINVAL;
- parm = RTA_DATA(tb[TCA_NAT_PARMS - 1]);
+ parm = nla_data(tb[TCA_NAT_PARMS]);
pc = tcf_hash_check(parm->index, a, bind, &nat_hash_info);
if (!pc) {
@@ -151,7 +158,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
else
iph->daddr = new_addr;
- nf_csum_replace4(&iph->check, addr, new_addr);
+ csum_replace4(&iph->check, addr, new_addr);
}
ihl = iph->ihl * 4;
@@ -169,7 +176,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
goto drop;
tcph = (void *)(skb_network_header(skb) + ihl);
- nf_proto_csum_replace4(&tcph->check, skb, addr, new_addr, 1);
+ inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, 1);
break;
}
case IPPROTO_UDP:
@@ -184,8 +191,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
udph = (void *)(skb_network_header(skb) + ihl);
if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) {
- nf_proto_csum_replace4(&udph->check, skb, addr,
- new_addr, 1);
+ inet_proto_csum_replace4(&udph->check, skb, addr,
+ new_addr, 1);
if (!udph->check)
udph->check = CSUM_MANGLED_0;
}
@@ -232,8 +239,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
else
iph->saddr = new_addr;
- nf_proto_csum_replace4(&icmph->checksum, skb, addr, new_addr,
- 1);
+ inet_proto_csum_replace4(&icmph->checksum, skb, addr, new_addr,
+ 1);
break;
}
default:
@@ -275,17 +282,17 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
opt->refcnt = p->tcf_refcnt - ref;
opt->bindcnt = p->tcf_bindcnt - bind;
- RTA_PUT(skb, TCA_NAT_PARMS, s, opt);
+ NLA_PUT(skb, TCA_NAT_PARMS, s, opt);
t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install);
t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse);
t.expires = jiffies_to_clock_t(p->tcf_tm.expires);
- RTA_PUT(skb, TCA_NAT_TM, sizeof(t), &t);
+ NLA_PUT(skb, TCA_NAT_TM, sizeof(t), &t);
kfree(opt);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
kfree(opt);
return -1;
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index b46fab5..3cc4cb9 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -33,26 +33,33 @@ static struct tcf_hashinfo pedit_hash_info = {
.lock = &pedit_lock,
};
-static int tcf_pedit_init(struct rtattr *rta, struct rtattr *est,
+static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
+ [TCA_PEDIT_PARMS] = { .len = sizeof(struct tcf_pedit) },
+};
+
+static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
- struct rtattr *tb[TCA_PEDIT_MAX];
+ struct nlattr *tb[TCA_PEDIT_MAX + 1];
struct tc_pedit *parm;
- int ret = 0;
+ int ret = 0, err;
struct tcf_pedit *p;
struct tcf_common *pc;
struct tc_pedit_key *keys = NULL;
int ksize;
- if (rta == NULL || rtattr_parse_nested(tb, TCA_PEDIT_MAX, rta) < 0)
+ if (nla == NULL)
return -EINVAL;
- if (tb[TCA_PEDIT_PARMS - 1] == NULL ||
- RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm))
+ err = nla_parse_nested(tb, TCA_PEDIT_MAX, nla, pedit_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_PEDIT_PARMS] == NULL)
return -EINVAL;
- parm = RTA_DATA(tb[TCA_PEDIT_PARMS-1]);
+ parm = nla_data(tb[TCA_PEDIT_PARMS]);
ksize = parm->nkeys * sizeof(struct tc_pedit_key);
- if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize)
+ if (nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm) + ksize)
return -EINVAL;
pc = tcf_hash_check(parm->index, a, bind, &pedit_hash_info);
@@ -206,15 +213,15 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
opt->refcnt = p->tcf_refcnt - ref;
opt->bindcnt = p->tcf_bindcnt - bind;
- RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt);
+ NLA_PUT(skb, TCA_PEDIT_PARMS, s, opt);
t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install);
t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse);
t.expires = jiffies_to_clock_t(p->tcf_tm.expires);
- RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t);
+ NLA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t);
kfree(opt);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
kfree(opt);
return -1;
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index a73e3e6d..0898120 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -54,7 +54,7 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c
{
struct tcf_common *p;
int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
- struct rtattr *r;
+ struct nlattr *nest;
read_lock_bh(&police_lock);
@@ -69,18 +69,19 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c
continue;
a->priv = p;
a->order = index;
- r = (struct rtattr *)skb_tail_pointer(skb);
- RTA_PUT(skb, a->order, 0, NULL);
+ nest = nla_nest_start(skb, a->order);
+ if (nest == NULL)
+ goto nla_put_failure;
if (type == RTM_DELACTION)
err = tcf_action_dump_1(skb, a, 0, 1);
else
err = tcf_action_dump_1(skb, a, 0, 0);
if (err < 0) {
index--;
- nlmsg_trim(skb, r);
+ nla_nest_cancel(skb, nest);
goto done;
}
- r->rta_len = skb_tail_pointer(skb) - (u8 *)r;
+ nla_nest_end(skb, nest);
n_i++;
}
}
@@ -90,8 +91,8 @@ done:
cb->args[0] += n_i;
return n_i;
-rtattr_failure:
- nlmsg_trim(skb, r);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
goto done;
}
@@ -118,33 +119,37 @@ static void tcf_police_destroy(struct tcf_police *p)
BUG_TRAP(0);
}
-static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
+static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
+ [TCA_POLICE_RATE] = { .len = TC_RTAB_SIZE },
+ [TCA_POLICE_PEAKRATE] = { .len = TC_RTAB_SIZE },
+ [TCA_POLICE_AVRATE] = { .type = NLA_U32 },
+ [TCA_POLICE_RESULT] = { .type = NLA_U32 },
+};
+
+static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
unsigned h;
int ret = 0, err;
- struct rtattr *tb[TCA_POLICE_MAX];
+ struct nlattr *tb[TCA_POLICE_MAX + 1];
struct tc_police *parm;
struct tcf_police *police;
struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
int size;
- if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
+ if (nla == NULL)
return -EINVAL;
- if (tb[TCA_POLICE_TBF-1] == NULL)
- return -EINVAL;
- size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]);
- if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
- return -EINVAL;
- parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
+ err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy);
+ if (err < 0)
+ return err;
- if (tb[TCA_POLICE_RESULT-1] != NULL &&
- RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
+ if (tb[TCA_POLICE_TBF] == NULL)
return -EINVAL;
- if (tb[TCA_POLICE_RESULT-1] != NULL &&
- RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
+ size = nla_len(tb[TCA_POLICE_TBF]);
+ if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
return -EINVAL;
+ parm = nla_data(tb[TCA_POLICE_TBF]);
if (parm->index) {
struct tcf_common *pc;
@@ -174,12 +179,12 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
override:
if (parm->rate.rate) {
err = -ENOMEM;
- R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
+ R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]);
if (R_tab == NULL)
goto failure;
if (parm->peakrate.rate) {
P_tab = qdisc_get_rtab(&parm->peakrate,
- tb[TCA_POLICE_PEAKRATE-1]);
+ tb[TCA_POLICE_PEAKRATE]);
if (P_tab == NULL) {
qdisc_put_rtab(R_tab);
goto failure;
@@ -197,8 +202,8 @@ override:
police->tcfp_P_tab = P_tab;
}
- if (tb[TCA_POLICE_RESULT-1])
- police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
+ if (tb[TCA_POLICE_RESULT])
+ police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
police->tcfp_toks = police->tcfp_burst = parm->burst;
police->tcfp_mtu = parm->mtu;
if (police->tcfp_mtu == 0) {
@@ -210,9 +215,8 @@ override:
police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
police->tcf_action = parm->action;
- if (tb[TCA_POLICE_AVRATE-1])
- police->tcfp_ewma_rate =
- *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
+ if (tb[TCA_POLICE_AVRATE])
+ police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
if (est)
gen_replace_estimator(&police->tcf_bstats,
&police->tcf_rate_est,
@@ -332,15 +336,14 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
opt.peakrate = police->tcfp_P_tab->rate;
else
memset(&opt.peakrate, 0, sizeof(opt.peakrate));
- RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
if (police->tcfp_result)
- RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
- &police->tcfp_result);
+ NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result);
if (police->tcfp_ewma_rate)
- RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
+ NLA_PUT_U32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index fb84ef3..fbde461 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -84,30 +84,37 @@ static int realloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
return alloc_defdata(d, datalen, defdata);
}
-static int tcf_simp_init(struct rtattr *rta, struct rtattr *est,
+static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
+ [TCA_DEF_PARMS] = { .len = sizeof(struct tc_defact) },
+};
+
+static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
- struct rtattr *tb[TCA_DEF_MAX];
+ struct nlattr *tb[TCA_DEF_MAX + 1];
struct tc_defact *parm;
struct tcf_defact *d;
struct tcf_common *pc;
void *defdata;
u32 datalen = 0;
- int ret = 0;
+ int ret = 0, err;
- if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)
+ if (nla == NULL)
return -EINVAL;
- if (tb[TCA_DEF_PARMS - 1] == NULL ||
- RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm))
+ err = nla_parse_nested(tb, TCA_DEF_MAX, nla, NULL);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_DEF_PARMS] == NULL)
return -EINVAL;
- parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);
- defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]);
+ parm = nla_data(tb[TCA_DEF_PARMS]);
+ defdata = nla_data(tb[TCA_DEF_DATA]);
if (defdata == NULL)
return -EINVAL;
- datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]);
+ datalen = nla_len(tb[TCA_DEF_DATA]);
if (datalen <= 0)
return -EINVAL;
@@ -164,15 +171,15 @@ static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
opt.refcnt = d->tcf_refcnt - ref;
opt.bindcnt = d->tcf_bindcnt - bind;
opt.action = d->tcf_action;
- RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
- RTA_PUT(skb, TCA_DEF_DATA, d->tcfd_datalen, d->tcfd_defdata);
+ NLA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_DEF_DATA, d->tcfd_datalen, d->tcfd_defdata);
t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install);
t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse);
t.expires = jiffies_to_clock_t(d->tcf_tm.expires);
- RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);
+ NLA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 0365797..3377ca0 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -23,33 +23,30 @@
#include <linux/init.h>
#include <linux/kmod.h>
#include <linux/netlink.h>
+#include <linux/err.h>
+#include <net/net_namespace.h>
+#include <net/sock.h>
#include <net/netlink.h>
#include <net/pkt_sched.h>
#include <net/pkt_cls.h>
-#if 0 /* control */
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define DPRINTK(format,args...)
-#endif
-
/* The list of all installed classifier types */
-static struct tcf_proto_ops *tcf_proto_base;
+static struct tcf_proto_ops *tcf_proto_base __read_mostly;
/* Protects list of registered TC modules. It is pure SMP lock. */
static DEFINE_RWLOCK(cls_mod_lock);
/* Find classifier type by string name */
-static struct tcf_proto_ops * tcf_proto_lookup_ops(struct rtattr *kind)
+static struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind)
{
struct tcf_proto_ops *t = NULL;
if (kind) {
read_lock(&cls_mod_lock);
for (t = tcf_proto_base; t; t = t->next) {
- if (rtattr_strcmp(kind, t->kind) == 0) {
+ if (nla_strcmp(kind, t->kind) == 0) {
if (!try_module_get(t->owner))
t = NULL;
break;
@@ -79,6 +76,7 @@ out:
write_unlock(&cls_mod_lock);
return rc;
}
+EXPORT_SYMBOL(register_tcf_proto_ops);
int unregister_tcf_proto_ops(struct tcf_proto_ops *ops)
{
@@ -98,6 +96,7 @@ out:
write_unlock(&cls_mod_lock);
return rc;
}
+EXPORT_SYMBOL(unregister_tcf_proto_ops);
static int tfilter_notify(struct sk_buff *oskb, struct nlmsghdr *n,
struct tcf_proto *tp, unsigned long fh, int event);
@@ -105,9 +104,9 @@ static int tfilter_notify(struct sk_buff *oskb, struct nlmsghdr *n,
/* Select new prio value from the range, managed by kernel. */
-static __inline__ u32 tcf_auto_prio(struct tcf_proto *tp)
+static inline u32 tcf_auto_prio(struct tcf_proto *tp)
{
- u32 first = TC_H_MAKE(0xC0000000U,0U);
+ u32 first = TC_H_MAKE(0xC0000000U, 0U);
if (tp)
first = tp->prio-1;
@@ -119,7 +118,8 @@ static __inline__ u32 tcf_auto_prio(struct tcf_proto *tp)
static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
- struct rtattr **tca;
+ struct net *net = skb->sk->sk_net;
+ struct nlattr *tca[TCA_MAX + 1];
struct tcmsg *t;
u32 protocol;
u32 prio;
@@ -130,13 +130,15 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
struct tcf_proto **back, **chain;
struct tcf_proto *tp;
struct tcf_proto_ops *tp_ops;
- struct Qdisc_class_ops *cops;
+ const struct Qdisc_class_ops *cops;
unsigned long cl;
unsigned long fh;
int err;
+ if (net != &init_net)
+ return -EINVAL;
+
replay:
- tca = arg;
t = NLMSG_DATA(n);
protocol = TC_H_MIN(t->tcm_info);
prio = TC_H_MAJ(t->tcm_info);
@@ -148,21 +150,29 @@ replay:
/* If no priority is given, user wants we allocated it. */
if (n->nlmsg_type != RTM_NEWTFILTER || !(n->nlmsg_flags&NLM_F_CREATE))
return -ENOENT;
- prio = TC_H_MAKE(0x80000000U,0U);
+ prio = TC_H_MAKE(0x80000000U, 0U);
}
/* Find head of filter chain. */
/* Find link */
- if ((dev = __dev_get_by_index(&init_net, t->tcm_ifindex)) == NULL)
+ dev = __dev_get_by_index(&init_net, t->tcm_ifindex);
+ if (dev == NULL)
return -ENODEV;
+ err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
+ if (err < 0)
+ return err;
+
/* Find qdisc */
if (!parent) {
q = dev->qdisc_sleeping;
parent = q->handle;
- } else if ((q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent))) == NULL)
- return -EINVAL;
+ } else {
+ q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent));
+ if (q == NULL)
+ return -EINVAL;
+ }
/* Is it classful? */
if ((cops = q->ops->cl_ops) == NULL)
@@ -196,7 +206,7 @@ replay:
if (tp == NULL) {
/* Proto-tcf does not exist, create new one */
- if (tca[TCA_KIND-1] == NULL || !protocol)
+ if (tca[TCA_KIND] == NULL || !protocol)
goto errout;
err = -ENOENT;
@@ -207,17 +217,18 @@ replay:
/* Create new proto tcf */
err = -ENOBUFS;
- if ((tp = kzalloc(sizeof(*tp), GFP_KERNEL)) == NULL)
+ tp = kzalloc(sizeof(*tp), GFP_KERNEL);
+ if (tp == NULL)
goto errout;
err = -EINVAL;
- tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND-1]);
+ tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND]);
if (tp_ops == NULL) {
#ifdef CONFIG_KMOD
- struct rtattr *kind = tca[TCA_KIND-1];
+ struct nlattr *kind = tca[TCA_KIND];
char name[IFNAMSIZ];
if (kind != NULL &&
- rtattr_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
+ nla_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
rtnl_unlock();
request_module("cls_%s", name);
rtnl_lock();
@@ -243,7 +254,9 @@ replay:
tp->q = q;
tp->classify = tp_ops->classify;
tp->classid = parent;
- if ((err = tp_ops->init(tp)) != 0) {
+
+ err = tp_ops->init(tp);
+ if (err != 0) {
module_put(tp_ops->owner);
kfree(tp);
goto errout;
@@ -254,7 +267,7 @@ replay:
*back = tp;
qdisc_unlock_tree(dev);
- } else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
+ } else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind))
goto errout;
fh = tp->ops->get(tp, t->tcm_handle);
@@ -272,13 +285,14 @@ replay:
}
err = -ENOENT;
- if (n->nlmsg_type != RTM_NEWTFILTER || !(n->nlmsg_flags&NLM_F_CREATE))
+ if (n->nlmsg_type != RTM_NEWTFILTER ||
+ !(n->nlmsg_flags & NLM_F_CREATE))
goto errout;
} else {
switch (n->nlmsg_type) {
case RTM_NEWTFILTER:
err = -EEXIST;
- if (n->nlmsg_flags&NLM_F_EXCL)
+ if (n->nlmsg_flags & NLM_F_EXCL)
goto errout;
break;
case RTM_DELTFILTER:
@@ -308,9 +322,8 @@ errout:
return err;
}
-static int
-tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh,
- u32 pid, u32 seq, u16 flags, int event)
+static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,
+ unsigned long fh, u32 pid, u32 seq, u16 flags, int event)
{
struct tcmsg *tcm;
struct nlmsghdr *nlh;
@@ -324,18 +337,18 @@ tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh,
tcm->tcm_ifindex = tp->q->dev->ifindex;
tcm->tcm_parent = tp->classid;
tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
- RTA_PUT(skb, TCA_KIND, IFNAMSIZ, tp->ops->kind);
+ NLA_PUT_STRING(skb, TCA_KIND, tp->ops->kind);
tcm->tcm_handle = fh;
if (RTM_DELTFILTER != event) {
tcm->tcm_handle = 0;
if (tp->ops->dump && tp->ops->dump(tp, fh, skb, tcm) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
}
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
return skb->len;
nlmsg_failure:
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -355,19 +368,20 @@ static int tfilter_notify(struct sk_buff *oskb, struct nlmsghdr *n,
return -EINVAL;
}
- return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC,
+ n->nlmsg_flags & NLM_F_ECHO);
}
-struct tcf_dump_args
-{
+struct tcf_dump_args {
struct tcf_walker w;
struct sk_buff *skb;
struct netlink_callback *cb;
};
-static int tcf_node_dump(struct tcf_proto *tp, unsigned long n, struct tcf_walker *arg)
+static int tcf_node_dump(struct tcf_proto *tp, unsigned long n,
+ struct tcf_walker *arg)
{
- struct tcf_dump_args *a = (void*)arg;
+ struct tcf_dump_args *a = (void *)arg;
return tcf_fill_node(a->skb, tp, n, NETLINK_CB(a->cb->skb).pid,
a->cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWTFILTER);
@@ -375,16 +389,20 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n, struct tcf_walke
static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct net *net = skb->sk->sk_net;
int t;
int s_t;
struct net_device *dev;
struct Qdisc *q;
struct tcf_proto *tp, **chain;
- struct tcmsg *tcm = (struct tcmsg*)NLMSG_DATA(cb->nlh);
+ struct tcmsg *tcm = (struct tcmsg *)NLMSG_DATA(cb->nlh);
unsigned long cl = 0;
- struct Qdisc_class_ops *cops;
+ const struct Qdisc_class_ops *cops;
struct tcf_dump_args arg;
+ if (net != &init_net)
+ return 0;
+
if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
return skb->len;
if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
@@ -421,9 +439,10 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
if (cb->args[1] == 0) {
if (tcf_fill_node(skb, tp, 0, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWTFILTER) <= 0) {
+ cb->nlh->nlmsg_seq, NLM_F_MULTI,
+ RTM_NEWTFILTER) <= 0)
break;
- }
+
cb->args[1] = 1;
}
if (tp->ops->walk == NULL)
@@ -450,8 +469,7 @@ out:
return skb->len;
}
-void
-tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
+void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
{
#ifdef CONFIG_NET_CLS_ACT
if (exts->action) {
@@ -460,49 +478,48 @@ tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
}
#endif
}
+EXPORT_SYMBOL(tcf_exts_destroy);
-
-int
-tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
- struct rtattr *rate_tlv, struct tcf_exts *exts,
+int tcf_exts_validate(struct tcf_proto *tp, struct nlattr **tb,
+ struct nlattr *rate_tlv, struct tcf_exts *exts,
struct tcf_ext_map *map)
{
memset(exts, 0, sizeof(*exts));
#ifdef CONFIG_NET_CLS_ACT
{
- int err;
struct tc_action *act;
- if (map->police && tb[map->police-1]) {
- act = tcf_action_init_1(tb[map->police-1], rate_tlv, "police",
- TCA_ACT_NOREPLACE, TCA_ACT_BIND, &err);
- if (act == NULL)
- return err;
+ if (map->police && tb[map->police]) {
+ act = tcf_action_init_1(tb[map->police], rate_tlv,
+ "police", TCA_ACT_NOREPLACE,
+ TCA_ACT_BIND);
+ if (IS_ERR(act))
+ return PTR_ERR(act);
act->type = TCA_OLD_COMPAT;
exts->action = act;
- } else if (map->action && tb[map->action-1]) {
- act = tcf_action_init(tb[map->action-1], rate_tlv, NULL,
- TCA_ACT_NOREPLACE, TCA_ACT_BIND, &err);
- if (act == NULL)
- return err;
+ } else if (map->action && tb[map->action]) {
+ act = tcf_action_init(tb[map->action], rate_tlv, NULL,
+ TCA_ACT_NOREPLACE, TCA_ACT_BIND);
+ if (IS_ERR(act))
+ return PTR_ERR(act);
exts->action = act;
}
}
#else
- if ((map->action && tb[map->action-1]) ||
- (map->police && tb[map->police-1]))
+ if ((map->action && tb[map->action]) ||
+ (map->police && tb[map->police]))
return -EOPNOTSUPP;
#endif
return 0;
}
+EXPORT_SYMBOL(tcf_exts_validate);
-void
-tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
- struct tcf_exts *src)
+void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
+ struct tcf_exts *src)
{
#ifdef CONFIG_NET_CLS_ACT
if (src->action) {
@@ -515,9 +532,9 @@ tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
}
#endif
}
+EXPORT_SYMBOL(tcf_exts_change);
-int
-tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
+int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
struct tcf_ext_map *map)
{
#ifdef CONFIG_NET_CLS_ACT
@@ -527,39 +544,45 @@ tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
* to work with both old and new modes of entering
* tc data even if iproute2 was newer - jhs
*/
- struct rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb);
+ struct nlattr *nest;
if (exts->action->type != TCA_OLD_COMPAT) {
- RTA_PUT(skb, map->action, 0, NULL);
+ nest = nla_nest_start(skb, map->action);
+ if (nest == NULL)
+ goto nla_put_failure;
if (tcf_action_dump(skb, exts->action, 0, 0) < 0)
- goto rtattr_failure;
- p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta;
+ goto nla_put_failure;
+ nla_nest_end(skb, nest);
} else if (map->police) {
- RTA_PUT(skb, map->police, 0, NULL);
+ nest = nla_nest_start(skb, map->police);
+ if (nest == NULL)
+ goto nla_put_failure;
if (tcf_action_dump_old(skb, exts->action, 0, 0) < 0)
- goto rtattr_failure;
- p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta;
+ goto nla_put_failure;
+ nla_nest_end(skb, nest);
}
}
#endif
return 0;
-rtattr_failure: __attribute__ ((unused))
+nla_put_failure: __attribute__ ((unused))
return -1;
}
+EXPORT_SYMBOL(tcf_exts_dump);
-int
-tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
- struct tcf_ext_map *map)
+
+int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
+ struct tcf_ext_map *map)
{
#ifdef CONFIG_NET_CLS_ACT
if (exts->action)
if (tcf_action_copy_stats(skb, exts->action, 1) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
#endif
return 0;
-rtattr_failure: __attribute__ ((unused))
+nla_put_failure: __attribute__ ((unused))
return -1;
}
+EXPORT_SYMBOL(tcf_exts_dump_stats);
static int __init tc_filter_init(void)
{
@@ -572,11 +595,3 @@ static int __init tc_filter_init(void)
}
subsys_initcall(tc_filter_init);
-
-EXPORT_SYMBOL(register_tcf_proto_ops);
-EXPORT_SYMBOL(unregister_tcf_proto_ops);
-EXPORT_SYMBOL(tcf_exts_validate);
-EXPORT_SYMBOL(tcf_exts_destroy);
-EXPORT_SYMBOL(tcf_exts_change);
-EXPORT_SYMBOL(tcf_exts_dump);
-EXPORT_SYMBOL(tcf_exts_dump_stats);
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 8dbcf27..bfb4342 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -129,28 +129,29 @@ static int basic_delete(struct tcf_proto *tp, unsigned long arg)
return -ENOENT;
}
+static const struct nla_policy basic_policy[TCA_BASIC_MAX + 1] = {
+ [TCA_BASIC_CLASSID] = { .type = NLA_U32 },
+ [TCA_BASIC_EMATCHES] = { .type = NLA_NESTED },
+};
+
static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
- unsigned long base, struct rtattr **tb,
- struct rtattr *est)
+ unsigned long base, struct nlattr **tb,
+ struct nlattr *est)
{
int err = -EINVAL;
struct tcf_exts e;
struct tcf_ematch_tree t;
- if (tb[TCA_BASIC_CLASSID-1])
- if (RTA_PAYLOAD(tb[TCA_BASIC_CLASSID-1]) < sizeof(u32))
- return err;
-
err = tcf_exts_validate(tp, tb, est, &e, &basic_ext_map);
if (err < 0)
return err;
- err = tcf_em_tree_validate(tp, tb[TCA_BASIC_EMATCHES-1], &t);
+ err = tcf_em_tree_validate(tp, tb[TCA_BASIC_EMATCHES], &t);
if (err < 0)
goto errout;
- if (tb[TCA_BASIC_CLASSID-1]) {
- f->res.classid = *(u32*)RTA_DATA(tb[TCA_BASIC_CLASSID-1]);
+ if (tb[TCA_BASIC_CLASSID]) {
+ f->res.classid = nla_get_u32(tb[TCA_BASIC_CLASSID]);
tcf_bind_filter(tp, &f->res, base);
}
@@ -164,23 +165,25 @@ errout:
}
static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
- struct rtattr **tca, unsigned long *arg)
+ struct nlattr **tca, unsigned long *arg)
{
- int err = -EINVAL;
+ int err;
struct basic_head *head = (struct basic_head *) tp->root;
- struct rtattr *tb[TCA_BASIC_MAX];
+ struct nlattr *tb[TCA_BASIC_MAX + 1];
struct basic_filter *f = (struct basic_filter *) *arg;
- if (tca[TCA_OPTIONS-1] == NULL)
+ if (tca[TCA_OPTIONS] == NULL)
return -EINVAL;
- if (rtattr_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS-1]) < 0)
- return -EINVAL;
+ err = nla_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS],
+ basic_policy);
+ if (err < 0)
+ return err;
if (f != NULL) {
if (handle && f->handle != handle)
return -EINVAL;
- return basic_set_parms(tp, f, base, tb, tca[TCA_RATE-1]);
+ return basic_set_parms(tp, f, base, tb, tca[TCA_RATE]);
}
err = -ENOBUFS;
@@ -206,7 +209,7 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
f->handle = head->hgenerator;
}
- err = basic_set_parms(tp, f, base, tb, tca[TCA_RATE-1]);
+ err = basic_set_parms(tp, f, base, tb, tca[TCA_RATE]);
if (err < 0)
goto errout;
@@ -245,33 +248,33 @@ static int basic_dump(struct tcf_proto *tp, unsigned long fh,
struct sk_buff *skb, struct tcmsg *t)
{
struct basic_filter *f = (struct basic_filter *) fh;
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
if (f == NULL)
return skb->len;
t->tcm_handle = f->handle;
- rta = (struct rtattr *) b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
if (f->res.classid)
- RTA_PUT(skb, TCA_BASIC_CLASSID, sizeof(u32), &f->res.classid);
+ NLA_PUT_U32(skb, TCA_BASIC_CLASSID, f->res.classid);
if (tcf_exts_dump(skb, &f->exts, &basic_ext_map) < 0 ||
tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
- rta->rta_len = skb_tail_pointer(skb) - b;
+ nla_nest_end(skb, nest);
return skb->len;
-rtattr_failure:
- nlmsg_trim(skb, b);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
return -1;
}
-static struct tcf_proto_ops cls_basic_ops = {
+static struct tcf_proto_ops cls_basic_ops __read_mostly = {
.kind = "basic",
.classify = basic_classify,
.init = basic_init,
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 8adbd6a..436a6e7 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -186,39 +186,41 @@ out:
return -EINVAL;
}
+static const struct nla_policy fw_policy[TCA_FW_MAX + 1] = {
+ [TCA_FW_CLASSID] = { .type = NLA_U32 },
+ [TCA_FW_INDEV] = { .type = NLA_STRING, .len = IFNAMSIZ },
+ [TCA_FW_MASK] = { .type = NLA_U32 },
+};
+
static int
fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
- struct rtattr **tb, struct rtattr **tca, unsigned long base)
+ struct nlattr **tb, struct nlattr **tca, unsigned long base)
{
struct fw_head *head = (struct fw_head *)tp->root;
struct tcf_exts e;
u32 mask;
int err;
- err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &fw_ext_map);
+ err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &fw_ext_map);
if (err < 0)
return err;
err = -EINVAL;
- if (tb[TCA_FW_CLASSID-1]) {
- if (RTA_PAYLOAD(tb[TCA_FW_CLASSID-1]) != sizeof(u32))
- goto errout;
- f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]);
+ if (tb[TCA_FW_CLASSID]) {
+ f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
tcf_bind_filter(tp, &f->res, base);
}
#ifdef CONFIG_NET_CLS_IND
- if (tb[TCA_FW_INDEV-1]) {
- err = tcf_change_indev(tp, f->indev, tb[TCA_FW_INDEV-1]);
+ if (tb[TCA_FW_INDEV]) {
+ err = tcf_change_indev(tp, f->indev, tb[TCA_FW_INDEV]);
if (err < 0)
goto errout;
}
#endif /* CONFIG_NET_CLS_IND */
- if (tb[TCA_FW_MASK-1]) {
- if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32))
- goto errout;
- mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]);
+ if (tb[TCA_FW_MASK]) {
+ mask = nla_get_u32(tb[TCA_FW_MASK]);
if (mask != head->mask)
goto errout;
} else if (head->mask != 0xFFFFFFFF)
@@ -234,20 +236,21 @@ errout:
static int fw_change(struct tcf_proto *tp, unsigned long base,
u32 handle,
- struct rtattr **tca,
+ struct nlattr **tca,
unsigned long *arg)
{
struct fw_head *head = (struct fw_head*)tp->root;
struct fw_filter *f = (struct fw_filter *) *arg;
- struct rtattr *opt = tca[TCA_OPTIONS-1];
- struct rtattr *tb[TCA_FW_MAX];
+ struct nlattr *opt = tca[TCA_OPTIONS];
+ struct nlattr *tb[TCA_FW_MAX + 1];
int err;
if (!opt)
return handle ? -EINVAL : 0;
- if (rtattr_parse_nested(tb, TCA_FW_MAX, opt) < 0)
- return -EINVAL;
+ err = nla_parse_nested(tb, TCA_FW_MAX, opt, fw_policy);
+ if (err < 0)
+ return err;
if (f != NULL) {
if (f->id != handle && handle)
@@ -260,11 +263,8 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
if (head == NULL) {
u32 mask = 0xFFFFFFFF;
- if (tb[TCA_FW_MASK-1]) {
- if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32))
- return -EINVAL;
- mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]);
- }
+ if (tb[TCA_FW_MASK])
+ mask = nla_get_u32(tb[TCA_FW_MASK]);
head = kzalloc(sizeof(struct fw_head), GFP_KERNEL);
if (head == NULL)
@@ -333,7 +333,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
struct fw_head *head = (struct fw_head *)tp->root;
struct fw_filter *f = (struct fw_filter*)fh;
unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
if (f == NULL)
return skb->len;
@@ -343,35 +343,35 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
if (!f->res.classid && !tcf_exts_is_available(&f->exts))
return skb->len;
- rta = (struct rtattr*)b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
if (f->res.classid)
- RTA_PUT(skb, TCA_FW_CLASSID, 4, &f->res.classid);
+ NLA_PUT_U32(skb, TCA_FW_CLASSID, f->res.classid);
#ifdef CONFIG_NET_CLS_IND
if (strlen(f->indev))
- RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev);
+ NLA_PUT_STRING(skb, TCA_FW_INDEV, f->indev);
#endif /* CONFIG_NET_CLS_IND */
if (head->mask != 0xFFFFFFFF)
- RTA_PUT(skb, TCA_FW_MASK, 4, &head->mask);
+ NLA_PUT_U32(skb, TCA_FW_MASK, head->mask);
if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
- rta->rta_len = skb_tail_pointer(skb) - b;
+ nla_nest_end(skb, nest);
if (tcf_exts_dump_stats(skb, &f->exts, &fw_ext_map) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
-static struct tcf_proto_ops cls_fw_ops = {
- .next = NULL,
+static struct tcf_proto_ops cls_fw_ops __read_mostly = {
.kind = "fw",
.classify = fw_classify,
.init = fw_init,
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 0a8409c..f7e7d39 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -323,9 +323,16 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg)
return 0;
}
+static const struct nla_policy route4_policy[TCA_ROUTE4_MAX + 1] = {
+ [TCA_ROUTE4_CLASSID] = { .type = NLA_U32 },
+ [TCA_ROUTE4_TO] = { .type = NLA_U32 },
+ [TCA_ROUTE4_FROM] = { .type = NLA_U32 },
+ [TCA_ROUTE4_IIF] = { .type = NLA_U32 },
+};
+
static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
struct route4_filter *f, u32 handle, struct route4_head *head,
- struct rtattr **tb, struct rtattr *est, int new)
+ struct nlattr **tb, struct nlattr *est, int new)
{
int err;
u32 id = 0, to = 0, nhandle = 0x8000;
@@ -339,34 +346,24 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
return err;
err = -EINVAL;
- if (tb[TCA_ROUTE4_CLASSID-1])
- if (RTA_PAYLOAD(tb[TCA_ROUTE4_CLASSID-1]) < sizeof(u32))
- goto errout;
-
- if (tb[TCA_ROUTE4_TO-1]) {
+ if (tb[TCA_ROUTE4_TO]) {
if (new && handle & 0x8000)
goto errout;
- if (RTA_PAYLOAD(tb[TCA_ROUTE4_TO-1]) < sizeof(u32))
- goto errout;
- to = *(u32*)RTA_DATA(tb[TCA_ROUTE4_TO-1]);
+ to = nla_get_u32(tb[TCA_ROUTE4_TO]);
if (to > 0xFF)
goto errout;
nhandle = to;
}
- if (tb[TCA_ROUTE4_FROM-1]) {
- if (tb[TCA_ROUTE4_IIF-1])
+ if (tb[TCA_ROUTE4_FROM]) {
+ if (tb[TCA_ROUTE4_IIF])
goto errout;
- if (RTA_PAYLOAD(tb[TCA_ROUTE4_FROM-1]) < sizeof(u32))
- goto errout;
- id = *(u32*)RTA_DATA(tb[TCA_ROUTE4_FROM-1]);
+ id = nla_get_u32(tb[TCA_ROUTE4_FROM]);
if (id > 0xFF)
goto errout;
nhandle |= id << 16;
- } else if (tb[TCA_ROUTE4_IIF-1]) {
- if (RTA_PAYLOAD(tb[TCA_ROUTE4_IIF-1]) < sizeof(u32))
- goto errout;
- id = *(u32*)RTA_DATA(tb[TCA_ROUTE4_IIF-1]);
+ } else if (tb[TCA_ROUTE4_IIF]) {
+ id = nla_get_u32(tb[TCA_ROUTE4_IIF]);
if (id > 0x7FFF)
goto errout;
nhandle |= (id | 0x8000) << 16;
@@ -398,20 +395,20 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
}
tcf_tree_lock(tp);
- if (tb[TCA_ROUTE4_TO-1])
+ if (tb[TCA_ROUTE4_TO])
f->id = to;
- if (tb[TCA_ROUTE4_FROM-1])
+ if (tb[TCA_ROUTE4_FROM])
f->id = to | id<<16;
- else if (tb[TCA_ROUTE4_IIF-1])
+ else if (tb[TCA_ROUTE4_IIF])
f->iif = id;
f->handle = nhandle;
f->bkt = b;
tcf_tree_unlock(tp);
- if (tb[TCA_ROUTE4_CLASSID-1]) {
- f->res.classid = *(u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID-1]);
+ if (tb[TCA_ROUTE4_CLASSID]) {
+ f->res.classid = nla_get_u32(tb[TCA_ROUTE4_CLASSID]);
tcf_bind_filter(tp, &f->res, base);
}
@@ -425,14 +422,14 @@ errout:
static int route4_change(struct tcf_proto *tp, unsigned long base,
u32 handle,
- struct rtattr **tca,
+ struct nlattr **tca,
unsigned long *arg)
{
struct route4_head *head = tp->root;
struct route4_filter *f, *f1, **fp;
struct route4_bucket *b;
- struct rtattr *opt = tca[TCA_OPTIONS-1];
- struct rtattr *tb[TCA_ROUTE4_MAX];
+ struct nlattr *opt = tca[TCA_OPTIONS];
+ struct nlattr *tb[TCA_ROUTE4_MAX + 1];
unsigned int h, th;
u32 old_handle = 0;
int err;
@@ -440,8 +437,9 @@ static int route4_change(struct tcf_proto *tp, unsigned long base,
if (opt == NULL)
return handle ? -EINVAL : 0;
- if (rtattr_parse_nested(tb, TCA_ROUTE4_MAX, opt) < 0)
- return -EINVAL;
+ err = nla_parse_nested(tb, TCA_ROUTE4_MAX, opt, route4_policy);
+ if (err < 0)
+ return err;
if ((f = (struct route4_filter*)*arg) != NULL) {
if (f->handle != handle && handle)
@@ -451,7 +449,7 @@ static int route4_change(struct tcf_proto *tp, unsigned long base,
old_handle = f->handle;
err = route4_set_parms(tp, base, f, handle, head, tb,
- tca[TCA_RATE-1], 0);
+ tca[TCA_RATE], 0);
if (err < 0)
return err;
@@ -474,7 +472,7 @@ static int route4_change(struct tcf_proto *tp, unsigned long base,
goto errout;
err = route4_set_parms(tp, base, f, handle, head, tb,
- tca[TCA_RATE-1], 1);
+ tca[TCA_RATE], 1);
if (err < 0)
goto errout;
@@ -550,7 +548,7 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh,
{
struct route4_filter *f = (struct route4_filter*)fh;
unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
u32 id;
if (f == NULL)
@@ -558,40 +556,40 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh,
t->tcm_handle = f->handle;
- rta = (struct rtattr*)b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
if (!(f->handle&0x8000)) {
id = f->id&0xFF;
- RTA_PUT(skb, TCA_ROUTE4_TO, sizeof(id), &id);
+ NLA_PUT_U32(skb, TCA_ROUTE4_TO, id);
}
if (f->handle&0x80000000) {
if ((f->handle>>16) != 0xFFFF)
- RTA_PUT(skb, TCA_ROUTE4_IIF, sizeof(f->iif), &f->iif);
+ NLA_PUT_U32(skb, TCA_ROUTE4_IIF, f->iif);
} else {
id = f->id>>16;
- RTA_PUT(skb, TCA_ROUTE4_FROM, sizeof(id), &id);
+ NLA_PUT_U32(skb, TCA_ROUTE4_FROM, id);
}
if (f->res.classid)
- RTA_PUT(skb, TCA_ROUTE4_CLASSID, 4, &f->res.classid);
+ NLA_PUT_U32(skb, TCA_ROUTE4_CLASSID, f->res.classid);
if (tcf_exts_dump(skb, &f->exts, &route_ext_map) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
- rta->rta_len = skb_tail_pointer(skb) - b;
+ nla_nest_end(skb, nest);
if (tcf_exts_dump_stats(skb, &f->exts, &route_ext_map) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
-static struct tcf_proto_ops cls_route4_ops = {
- .next = NULL,
+static struct tcf_proto_ops cls_route4_ops __read_mostly = {
.kind = "route",
.classify = route4_classify,
.init = route4_init,
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 22f9ede..7034ea4 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -397,17 +397,26 @@ static u32 gen_tunnel(struct rsvp_head *data)
return 0;
}
+static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = {
+ [TCA_RSVP_CLASSID] = { .type = NLA_U32 },
+ [TCA_RSVP_DST] = { .type = NLA_BINARY,
+ .len = RSVP_DST_LEN * sizeof(u32) },
+ [TCA_RSVP_SRC] = { .type = NLA_BINARY,
+ .len = RSVP_DST_LEN * sizeof(u32) },
+ [TCA_RSVP_PINFO] = { .len = sizeof(struct tc_rsvp_pinfo) },
+};
+
static int rsvp_change(struct tcf_proto *tp, unsigned long base,
u32 handle,
- struct rtattr **tca,
+ struct nlattr **tca,
unsigned long *arg)
{
struct rsvp_head *data = tp->root;
struct rsvp_filter *f, **fp;
struct rsvp_session *s, **sp;
struct tc_rsvp_pinfo *pinfo = NULL;
- struct rtattr *opt = tca[TCA_OPTIONS-1];
- struct rtattr *tb[TCA_RSVP_MAX];
+ struct nlattr *opt = tca[TCA_OPTIONS-1];
+ struct nlattr *tb[TCA_RSVP_MAX + 1];
struct tcf_exts e;
unsigned h1, h2;
__be32 *dst;
@@ -416,8 +425,9 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
if (opt == NULL)
return handle ? -EINVAL : 0;
- if (rtattr_parse_nested(tb, TCA_RSVP_MAX, opt) < 0)
- return -EINVAL;
+ err = nla_parse_nested(tb, TCA_RSVP_MAX, opt, rsvp_policy);
+ if (err < 0)
+ return err;
err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &rsvp_ext_map);
if (err < 0)
@@ -429,7 +439,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
if (f->handle != handle && handle)
goto errout2;
if (tb[TCA_RSVP_CLASSID-1]) {
- f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]);
+ f->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID-1]);
tcf_bind_filter(tp, &f->res, base);
}
@@ -451,31 +461,18 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
h2 = 16;
if (tb[TCA_RSVP_SRC-1]) {
- err = -EINVAL;
- if (RTA_PAYLOAD(tb[TCA_RSVP_SRC-1]) != sizeof(f->src))
- goto errout;
- memcpy(f->src, RTA_DATA(tb[TCA_RSVP_SRC-1]), sizeof(f->src));
+ memcpy(f->src, nla_data(tb[TCA_RSVP_SRC-1]), sizeof(f->src));
h2 = hash_src(f->src);
}
if (tb[TCA_RSVP_PINFO-1]) {
- err = -EINVAL;
- if (RTA_PAYLOAD(tb[TCA_RSVP_PINFO-1]) < sizeof(struct tc_rsvp_pinfo))
- goto errout;
- pinfo = RTA_DATA(tb[TCA_RSVP_PINFO-1]);
+ pinfo = nla_data(tb[TCA_RSVP_PINFO-1]);
f->spi = pinfo->spi;
f->tunnelhdr = pinfo->tunnelhdr;
}
- if (tb[TCA_RSVP_CLASSID-1]) {
- err = -EINVAL;
- if (RTA_PAYLOAD(tb[TCA_RSVP_CLASSID-1]) != 4)
- goto errout;
- f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]);
- }
+ if (tb[TCA_RSVP_CLASSID-1])
+ f->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID-1]);
- err = -EINVAL;
- if (RTA_PAYLOAD(tb[TCA_RSVP_DST-1]) != sizeof(f->src))
- goto errout;
- dst = RTA_DATA(tb[TCA_RSVP_DST-1]);
+ dst = nla_data(tb[TCA_RSVP_DST-1]);
h1 = hash_dst(dst, pinfo ? pinfo->protocol : 0, pinfo ? pinfo->tunnelid : 0);
err = -ENOMEM;
@@ -594,7 +591,7 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
struct rsvp_filter *f = (struct rsvp_filter*)fh;
struct rsvp_session *s;
unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
struct tc_rsvp_pinfo pinfo;
if (f == NULL)
@@ -603,33 +600,33 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
t->tcm_handle = f->handle;
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
- rta = (struct rtattr*)b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
-
- RTA_PUT(skb, TCA_RSVP_DST, sizeof(s->dst), &s->dst);
+ NLA_PUT(skb, TCA_RSVP_DST, sizeof(s->dst), &s->dst);
pinfo.dpi = s->dpi;
pinfo.spi = f->spi;
pinfo.protocol = s->protocol;
pinfo.tunnelid = s->tunnelid;
pinfo.tunnelhdr = f->tunnelhdr;
pinfo.pad = 0;
- RTA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo);
+ NLA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo);
if (f->res.classid)
- RTA_PUT(skb, TCA_RSVP_CLASSID, 4, &f->res.classid);
+ NLA_PUT_U32(skb, TCA_RSVP_CLASSID, f->res.classid);
if (((f->handle>>8)&0xFF) != 16)
- RTA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src);
+ NLA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src);
if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
- rta->rta_len = skb_tail_pointer(skb) - b;
+ nla_nest_end(skb, nest);
if (tcf_exts_dump_stats(skb, &f->exts, &rsvp_ext_map) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 2314820..ee60b2d 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -29,19 +29,6 @@
#define DEFAULT_HASH_SIZE 64 /* optimized for diffserv */
-#if 1 /* control */
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define DPRINTK(format,args...)
-#endif
-
-#if 0 /* data */
-#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define D2PRINTK(format,args...)
-#endif
-
-
#define PRIV(tp) ((struct tcindex_data *) (tp)->root)
@@ -104,7 +91,8 @@ static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
struct tcindex_filter_result *f;
int key = (skb->tc_index & p->mask) >> p->shift;
- D2PRINTK("tcindex_classify(skb %p,tp %p,res %p),p %p\n",skb,tp,res,p);
+ pr_debug("tcindex_classify(skb %p,tp %p,res %p),p %p\n",
+ skb, tp, res, p);
f = tcindex_lookup(p, key);
if (!f) {
@@ -112,11 +100,11 @@ static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
return -1;
res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle), key);
res->class = 0;
- D2PRINTK("alg 0x%x\n",res->classid);
+ pr_debug("alg 0x%x\n", res->classid);
return 0;
}
*res = f->res;
- D2PRINTK("map 0x%x\n",res->classid);
+ pr_debug("map 0x%x\n", res->classid);
return tcf_exts_exec(skb, &f->exts, res);
}
@@ -127,7 +115,7 @@ static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
struct tcindex_data *p = PRIV(tp);
struct tcindex_filter_result *r;
- DPRINTK("tcindex_get(tp %p,handle 0x%08x)\n",tp,handle);
+ pr_debug("tcindex_get(tp %p,handle 0x%08x)\n", tp, handle);
if (p->perfect && handle >= p->alloc_hash)
return 0;
r = tcindex_lookup(p, handle);
@@ -137,7 +125,7 @@ static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
static void tcindex_put(struct tcf_proto *tp, unsigned long f)
{
- DPRINTK("tcindex_put(tp %p,f 0x%lx)\n",tp,f);
+ pr_debug("tcindex_put(tp %p,f 0x%lx)\n", tp, f);
}
@@ -145,8 +133,8 @@ static int tcindex_init(struct tcf_proto *tp)
{
struct tcindex_data *p;
- DPRINTK("tcindex_init(tp %p)\n",tp);
- p = kzalloc(sizeof(struct tcindex_data),GFP_KERNEL);
+ pr_debug("tcindex_init(tp %p)\n", tp);
+ p = kzalloc(sizeof(struct tcindex_data), GFP_KERNEL);
if (!p)
return -ENOMEM;
@@ -166,7 +154,7 @@ __tcindex_delete(struct tcf_proto *tp, unsigned long arg, int lock)
struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg;
struct tcindex_filter *f = NULL;
- DPRINTK("tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n",tp,arg,p,f);
+ pr_debug("tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n", tp, arg, p, f);
if (p->perfect) {
if (!r->res.class)
return -ENOENT;
@@ -205,10 +193,18 @@ valid_perfect_hash(struct tcindex_data *p)
return p->hash > (p->mask >> p->shift);
}
+static const struct nla_policy tcindex_policy[TCA_TCINDEX_MAX + 1] = {
+ [TCA_TCINDEX_HASH] = { .type = NLA_U32 },
+ [TCA_TCINDEX_MASK] = { .type = NLA_U16 },
+ [TCA_TCINDEX_SHIFT] = { .type = NLA_U32 },
+ [TCA_TCINDEX_FALL_THROUGH] = { .type = NLA_U32 },
+ [TCA_TCINDEX_CLASSID] = { .type = NLA_U32 },
+};
+
static int
tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
struct tcindex_data *p, struct tcindex_filter_result *r,
- struct rtattr **tb, struct rtattr *est)
+ struct nlattr **tb, struct nlattr *est)
{
int err, balloc = 0;
struct tcindex_filter_result new_filter_result, *old_r = r;
@@ -229,24 +225,14 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
else
memset(&cr, 0, sizeof(cr));
- err = -EINVAL;
- if (tb[TCA_TCINDEX_HASH-1]) {
- if (RTA_PAYLOAD(tb[TCA_TCINDEX_HASH-1]) < sizeof(u32))
- goto errout;
- cp.hash = *(u32 *) RTA_DATA(tb[TCA_TCINDEX_HASH-1]);
- }
+ if (tb[TCA_TCINDEX_HASH])
+ cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
- if (tb[TCA_TCINDEX_MASK-1]) {
- if (RTA_PAYLOAD(tb[TCA_TCINDEX_MASK-1]) < sizeof(u16))
- goto errout;
- cp.mask = *(u16 *) RTA_DATA(tb[TCA_TCINDEX_MASK-1]);
- }
+ if (tb[TCA_TCINDEX_MASK])
+ cp.mask = nla_get_u16(tb[TCA_TCINDEX_MASK]);
- if (tb[TCA_TCINDEX_SHIFT-1]) {
- if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(int))
- goto errout;
- cp.shift = *(int *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]);
- }
+ if (tb[TCA_TCINDEX_SHIFT])
+ cp.shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]);
err = -EBUSY;
/* Hash already allocated, make sure that we still meet the
@@ -260,12 +246,8 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
goto errout;
err = -EINVAL;
- if (tb[TCA_TCINDEX_FALL_THROUGH-1]) {
- if (RTA_PAYLOAD(tb[TCA_TCINDEX_FALL_THROUGH-1]) < sizeof(u32))
- goto errout;
- cp.fall_through =
- *(u32 *) RTA_DATA(tb[TCA_TCINDEX_FALL_THROUGH-1]);
- }
+ if (tb[TCA_TCINDEX_FALL_THROUGH])
+ cp.fall_through = nla_get_u32(tb[TCA_TCINDEX_FALL_THROUGH]);
if (!cp.hash) {
/* Hash not specified, use perfect hash if the upper limit
@@ -316,8 +298,8 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
goto errout_alloc;
}
- if (tb[TCA_TCINDEX_CLASSID-1]) {
- cr.res.classid = *(u32 *) RTA_DATA(tb[TCA_TCINDEX_CLASSID-1]);
+ if (tb[TCA_TCINDEX_CLASSID]) {
+ cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
tcf_bind_filter(tp, &cr.res, base);
}
@@ -356,34 +338,36 @@ errout:
static int
tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle,
- struct rtattr **tca, unsigned long *arg)
+ struct nlattr **tca, unsigned long *arg)
{
- struct rtattr *opt = tca[TCA_OPTIONS-1];
- struct rtattr *tb[TCA_TCINDEX_MAX];
+ struct nlattr *opt = tca[TCA_OPTIONS];
+ struct nlattr *tb[TCA_TCINDEX_MAX + 1];
struct tcindex_data *p = PRIV(tp);
struct tcindex_filter_result *r = (struct tcindex_filter_result *) *arg;
+ int err;
- DPRINTK("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
+ pr_debug("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
"p %p,r %p,*arg 0x%lx\n",
tp, handle, tca, arg, opt, p, r, arg ? *arg : 0L);
if (!opt)
return 0;
- if (rtattr_parse_nested(tb, TCA_TCINDEX_MAX, opt) < 0)
- return -EINVAL;
+ err = nla_parse_nested(tb, TCA_TCINDEX_MAX, opt, tcindex_policy);
+ if (err < 0)
+ return err;
- return tcindex_set_parms(tp, base, handle, p, r, tb, tca[TCA_RATE-1]);
+ return tcindex_set_parms(tp, base, handle, p, r, tb, tca[TCA_RATE]);
}
static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
{
struct tcindex_data *p = PRIV(tp);
- struct tcindex_filter *f,*next;
+ struct tcindex_filter *f, *next;
int i;
- DPRINTK("tcindex_walk(tp %p,walker %p),p %p\n",tp,walker,p);
+ pr_debug("tcindex_walk(tp %p,walker %p),p %p\n", tp, walker, p);
if (p->perfect) {
for (i = 0; i < p->hash; i++) {
if (!p->perfect[i].res.class)
@@ -405,7 +389,7 @@ static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
for (f = p->h[i]; f; f = next) {
next = f->next;
if (walker->count >= walker->skip) {
- if (walker->fn(tp,(unsigned long) &f->result,
+ if (walker->fn(tp, (unsigned long) &f->result,
walker) < 0) {
walker->stop = 1;
return;
@@ -429,11 +413,11 @@ static void tcindex_destroy(struct tcf_proto *tp)
struct tcindex_data *p = PRIV(tp);
struct tcf_walker walker;
- DPRINTK("tcindex_destroy(tp %p),p %p\n",tp,p);
+ pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p);
walker.count = 0;
walker.skip = 0;
walker.fn = &tcindex_destroy_element;
- tcindex_walk(tp,&walker);
+ tcindex_walk(tp, &walker);
kfree(p->perfect);
kfree(p->h);
kfree(p);
@@ -447,21 +431,23 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
struct tcindex_data *p = PRIV(tp);
struct tcindex_filter_result *r = (struct tcindex_filter_result *) fh;
unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
+
+ pr_debug("tcindex_dump(tp %p,fh 0x%lx,skb %p,t %p),p %p,r %p,b %p\n",
+ tp, fh, skb, t, p, r, b);
+ pr_debug("p->perfect %p p->h %p\n", p->perfect, p->h);
+
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
- DPRINTK("tcindex_dump(tp %p,fh 0x%lx,skb %p,t %p),p %p,r %p,b %p\n",
- tp,fh,skb,t,p,r,b);
- DPRINTK("p->perfect %p p->h %p\n",p->perfect,p->h);
- rta = (struct rtattr *) b;
- RTA_PUT(skb,TCA_OPTIONS,0,NULL);
if (!fh) {
t->tcm_handle = ~0; /* whatever ... */
- RTA_PUT(skb,TCA_TCINDEX_HASH,sizeof(p->hash),&p->hash);
- RTA_PUT(skb,TCA_TCINDEX_MASK,sizeof(p->mask),&p->mask);
- RTA_PUT(skb,TCA_TCINDEX_SHIFT,sizeof(p->shift),&p->shift);
- RTA_PUT(skb,TCA_TCINDEX_FALL_THROUGH,sizeof(p->fall_through),
- &p->fall_through);
- rta->rta_len = skb_tail_pointer(skb) - b;
+ NLA_PUT_U32(skb, TCA_TCINDEX_HASH, p->hash);
+ NLA_PUT_U16(skb, TCA_TCINDEX_MASK, p->mask);
+ NLA_PUT_U32(skb, TCA_TCINDEX_SHIFT, p->shift);
+ NLA_PUT_U32(skb, TCA_TCINDEX_FALL_THROUGH, p->fall_through);
+ nla_nest_end(skb, nest);
} else {
if (p->perfect) {
t->tcm_handle = r-p->perfect;
@@ -478,27 +464,26 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
}
}
}
- DPRINTK("handle = %d\n",t->tcm_handle);
+ pr_debug("handle = %d\n", t->tcm_handle);
if (r->res.class)
- RTA_PUT(skb, TCA_TCINDEX_CLASSID, 4, &r->res.classid);
+ NLA_PUT_U32(skb, TCA_TCINDEX_CLASSID, r->res.classid);
if (tcf_exts_dump(skb, &r->exts, &tcindex_ext_map) < 0)
- goto rtattr_failure;
- rta->rta_len = skb_tail_pointer(skb) - b;
+ goto nla_put_failure;
+ nla_nest_end(skb, nest);
if (tcf_exts_dump_stats(skb, &r->exts, &tcindex_ext_map) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
}
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
-static struct tcf_proto_ops cls_tcindex_ops = {
- .next = NULL,
+static struct tcf_proto_ops cls_tcindex_ops __read_mostly = {
.kind = "tcindex",
.classify = tcindex_classify,
.init = tcindex_init,
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index c390082..e8a7756 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -460,10 +460,20 @@ static u32 gen_new_kid(struct tc_u_hnode *ht, u32 handle)
return handle|(i>0xFFF ? 0xFFF : i);
}
+static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
+ [TCA_U32_CLASSID] = { .type = NLA_U32 },
+ [TCA_U32_HASH] = { .type = NLA_U32 },
+ [TCA_U32_LINK] = { .type = NLA_U32 },
+ [TCA_U32_DIVISOR] = { .type = NLA_U32 },
+ [TCA_U32_SEL] = { .len = sizeof(struct tc_u32_sel) },
+ [TCA_U32_INDEV] = { .type = NLA_STRING, .len = IFNAMSIZ },
+ [TCA_U32_MARK] = { .len = sizeof(struct tc_u32_mark) },
+};
+
static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
struct tc_u_hnode *ht,
- struct tc_u_knode *n, struct rtattr **tb,
- struct rtattr *est)
+ struct tc_u_knode *n, struct nlattr **tb,
+ struct nlattr *est)
{
int err;
struct tcf_exts e;
@@ -473,8 +483,8 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
return err;
err = -EINVAL;
- if (tb[TCA_U32_LINK-1]) {
- u32 handle = *(u32*)RTA_DATA(tb[TCA_U32_LINK-1]);
+ if (tb[TCA_U32_LINK]) {
+ u32 handle = nla_get_u32(tb[TCA_U32_LINK]);
struct tc_u_hnode *ht_down = NULL;
if (TC_U32_KEY(handle))
@@ -495,14 +505,14 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
if (ht_down)
ht_down->refcnt--;
}
- if (tb[TCA_U32_CLASSID-1]) {
- n->res.classid = *(u32*)RTA_DATA(tb[TCA_U32_CLASSID-1]);
+ if (tb[TCA_U32_CLASSID]) {
+ n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
tcf_bind_filter(tp, &n->res, base);
}
#ifdef CONFIG_NET_CLS_IND
- if (tb[TCA_U32_INDEV-1]) {
- err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]);
+ if (tb[TCA_U32_INDEV]) {
+ err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV]);
if (err < 0)
goto errout;
}
@@ -516,33 +526,34 @@ errout:
}
static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
- struct rtattr **tca,
+ struct nlattr **tca,
unsigned long *arg)
{
struct tc_u_common *tp_c = tp->data;
struct tc_u_hnode *ht;
struct tc_u_knode *n;
struct tc_u32_sel *s;
- struct rtattr *opt = tca[TCA_OPTIONS-1];
- struct rtattr *tb[TCA_U32_MAX];
+ struct nlattr *opt = tca[TCA_OPTIONS];
+ struct nlattr *tb[TCA_U32_MAX + 1];
u32 htid;
int err;
if (opt == NULL)
return handle ? -EINVAL : 0;
- if (rtattr_parse_nested(tb, TCA_U32_MAX, opt) < 0)
- return -EINVAL;
+ err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy);
+ if (err < 0)
+ return err;
if ((n = (struct tc_u_knode*)*arg) != NULL) {
if (TC_U32_KEY(n->handle) == 0)
return -EINVAL;
- return u32_set_parms(tp, base, n->ht_up, n, tb, tca[TCA_RATE-1]);
+ return u32_set_parms(tp, base, n->ht_up, n, tb, tca[TCA_RATE]);
}
- if (tb[TCA_U32_DIVISOR-1]) {
- unsigned divisor = *(unsigned*)RTA_DATA(tb[TCA_U32_DIVISOR-1]);
+ if (tb[TCA_U32_DIVISOR]) {
+ unsigned divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
if (--divisor > 0x100)
return -EINVAL;
@@ -567,8 +578,8 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
return 0;
}
- if (tb[TCA_U32_HASH-1]) {
- htid = *(unsigned*)RTA_DATA(tb[TCA_U32_HASH-1]);
+ if (tb[TCA_U32_HASH]) {
+ htid = nla_get_u32(tb[TCA_U32_HASH]);
if (TC_U32_HTID(htid) == TC_U32_ROOT) {
ht = tp->root;
htid = ht->handle;
@@ -592,11 +603,10 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
} else
handle = gen_new_kid(ht, htid);
- if (tb[TCA_U32_SEL-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_U32_SEL-1]) < sizeof(struct tc_u32_sel))
+ if (tb[TCA_U32_SEL] == NULL)
return -EINVAL;
- s = RTA_DATA(tb[TCA_U32_SEL-1]);
+ s = nla_data(tb[TCA_U32_SEL]);
n = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL);
if (n == NULL)
@@ -616,23 +626,16 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;
#ifdef CONFIG_CLS_U32_MARK
- if (tb[TCA_U32_MARK-1]) {
+ if (tb[TCA_U32_MARK]) {
struct tc_u32_mark *mark;
- if (RTA_PAYLOAD(tb[TCA_U32_MARK-1]) < sizeof(struct tc_u32_mark)) {
-#ifdef CONFIG_CLS_U32_PERF
- kfree(n->pf);
-#endif
- kfree(n);
- return -EINVAL;
- }
- mark = RTA_DATA(tb[TCA_U32_MARK-1]);
+ mark = nla_data(tb[TCA_U32_MARK]);
memcpy(&n->mark, mark, sizeof(struct tc_u32_mark));
n->mark.success = 0;
}
#endif
- err = u32_set_parms(tp, base, ht, n, tb, tca[TCA_RATE-1]);
+ err = u32_set_parms(tp, base, ht, n, tb, tca[TCA_RATE]);
if (err == 0) {
struct tc_u_knode **ins;
for (ins = &ht->ht[TC_U32_HASH(handle)]; *ins; ins = &(*ins)->next)
@@ -693,66 +696,66 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
struct sk_buff *skb, struct tcmsg *t)
{
struct tc_u_knode *n = (struct tc_u_knode*)fh;
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
if (n == NULL)
return skb->len;
t->tcm_handle = n->handle;
- rta = (struct rtattr*)b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
if (TC_U32_KEY(n->handle) == 0) {
struct tc_u_hnode *ht = (struct tc_u_hnode*)fh;
u32 divisor = ht->divisor+1;
- RTA_PUT(skb, TCA_U32_DIVISOR, 4, &divisor);
+ NLA_PUT_U32(skb, TCA_U32_DIVISOR, divisor);
} else {
- RTA_PUT(skb, TCA_U32_SEL,
+ NLA_PUT(skb, TCA_U32_SEL,
sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key),
&n->sel);
if (n->ht_up) {
u32 htid = n->handle & 0xFFFFF000;
- RTA_PUT(skb, TCA_U32_HASH, 4, &htid);
+ NLA_PUT_U32(skb, TCA_U32_HASH, htid);
}
if (n->res.classid)
- RTA_PUT(skb, TCA_U32_CLASSID, 4, &n->res.classid);
+ NLA_PUT_U32(skb, TCA_U32_CLASSID, n->res.classid);
if (n->ht_down)
- RTA_PUT(skb, TCA_U32_LINK, 4, &n->ht_down->handle);
+ NLA_PUT_U32(skb, TCA_U32_LINK, n->ht_down->handle);
#ifdef CONFIG_CLS_U32_MARK
if (n->mark.val || n->mark.mask)
- RTA_PUT(skb, TCA_U32_MARK, sizeof(n->mark), &n->mark);
+ NLA_PUT(skb, TCA_U32_MARK, sizeof(n->mark), &n->mark);
#endif
if (tcf_exts_dump(skb, &n->exts, &u32_ext_map) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
#ifdef CONFIG_NET_CLS_IND
if(strlen(n->indev))
- RTA_PUT(skb, TCA_U32_INDEV, IFNAMSIZ, n->indev);
+ NLA_PUT_STRING(skb, TCA_U32_INDEV, n->indev);
#endif
#ifdef CONFIG_CLS_U32_PERF
- RTA_PUT(skb, TCA_U32_PCNT,
+ NLA_PUT(skb, TCA_U32_PCNT,
sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(u64),
n->pf);
#endif
}
- rta->rta_len = skb_tail_pointer(skb) - b;
+ nla_nest_end(skb, nest);
+
if (TC_U32_KEY(n->handle))
if (tcf_exts_dump_stats(skb, &n->exts, &u32_ext_map) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
return skb->len;
-rtattr_failure:
- nlmsg_trim(skb, b);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
return -1;
}
-static struct tcf_proto_ops cls_u32_ops = {
- .next = NULL,
+static struct tcf_proto_ops cls_u32_ops __read_mostly = {
.kind = "u32",
.classify = u32_classify,
.init = u32_init,
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index ceda889..a1e5619 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -542,11 +542,11 @@ static int meta_var_compare(struct meta_obj *a, struct meta_obj *b)
return r;
}
-static int meta_var_change(struct meta_value *dst, struct rtattr *rta)
+static int meta_var_change(struct meta_value *dst, struct nlattr *nla)
{
- int len = RTA_PAYLOAD(rta);
+ int len = nla_len(nla);
- dst->val = (unsigned long)kmemdup(RTA_DATA(rta), len, GFP_KERNEL);
+ dst->val = (unsigned long)kmemdup(nla_data(nla), len, GFP_KERNEL);
if (dst->val == 0UL)
return -ENOMEM;
dst->len = len;
@@ -570,10 +570,10 @@ static void meta_var_apply_extras(struct meta_value *v,
static int meta_var_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
{
if (v->val && v->len)
- RTA_PUT(skb, tlv, v->len, (void *) v->val);
+ NLA_PUT(skb, tlv, v->len, (void *) v->val);
return 0;
-rtattr_failure:
+nla_put_failure:
return -1;
}
@@ -594,13 +594,13 @@ static int meta_int_compare(struct meta_obj *a, struct meta_obj *b)
return 1;
}
-static int meta_int_change(struct meta_value *dst, struct rtattr *rta)
+static int meta_int_change(struct meta_value *dst, struct nlattr *nla)
{
- if (RTA_PAYLOAD(rta) >= sizeof(unsigned long)) {
- dst->val = *(unsigned long *) RTA_DATA(rta);
+ if (nla_len(nla) >= sizeof(unsigned long)) {
+ dst->val = *(unsigned long *) nla_data(nla);
dst->len = sizeof(unsigned long);
- } else if (RTA_PAYLOAD(rta) == sizeof(u32)) {
- dst->val = *(u32 *) RTA_DATA(rta);
+ } else if (nla_len(nla) == sizeof(u32)) {
+ dst->val = nla_get_u32(nla);
dst->len = sizeof(u32);
} else
return -EINVAL;
@@ -621,15 +621,14 @@ static void meta_int_apply_extras(struct meta_value *v,
static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
{
if (v->len == sizeof(unsigned long))
- RTA_PUT(skb, tlv, sizeof(unsigned long), &v->val);
+ NLA_PUT(skb, tlv, sizeof(unsigned long), &v->val);
else if (v->len == sizeof(u32)) {
- u32 d = v->val;
- RTA_PUT(skb, tlv, sizeof(d), &d);
+ NLA_PUT_U32(skb, tlv, v->val);
}
return 0;
-rtattr_failure:
+nla_put_failure:
return -1;
}
@@ -641,7 +640,7 @@ struct meta_type_ops
{
void (*destroy)(struct meta_value *);
int (*compare)(struct meta_obj *, struct meta_obj *);
- int (*change)(struct meta_value *, struct rtattr *);
+ int (*change)(struct meta_value *, struct nlattr *);
void (*apply_extras)(struct meta_value *, struct meta_obj *);
int (*dump)(struct sk_buff *, struct meta_value *, int);
};
@@ -729,13 +728,13 @@ static inline void meta_delete(struct meta_match *meta)
kfree(meta);
}
-static inline int meta_change_data(struct meta_value *dst, struct rtattr *rta)
+static inline int meta_change_data(struct meta_value *dst, struct nlattr *nla)
{
- if (rta) {
- if (RTA_PAYLOAD(rta) == 0)
+ if (nla) {
+ if (nla_len(nla) == 0)
return -EINVAL;
- return meta_type_ops(dst)->change(dst, rta);
+ return meta_type_ops(dst)->change(dst, nla);
}
return 0;
@@ -746,21 +745,26 @@ static inline int meta_is_supported(struct meta_value *val)
return (!meta_id(val) || meta_ops(val)->get);
}
+static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = {
+ [TCA_EM_META_HDR] = { .len = sizeof(struct tcf_meta_hdr) },
+};
+
static int em_meta_change(struct tcf_proto *tp, void *data, int len,
struct tcf_ematch *m)
{
- int err = -EINVAL;
- struct rtattr *tb[TCA_EM_META_MAX];
+ int err;
+ struct nlattr *tb[TCA_EM_META_MAX + 1];
struct tcf_meta_hdr *hdr;
struct meta_match *meta = NULL;
- if (rtattr_parse(tb, TCA_EM_META_MAX, data, len) < 0)
+ err = nla_parse(tb, TCA_EM_META_MAX, data, len, meta_policy);
+ if (err < 0)
goto errout;
- if (tb[TCA_EM_META_HDR-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_EM_META_HDR-1]) < sizeof(*hdr))
+ err = -EINVAL;
+ if (tb[TCA_EM_META_HDR] == NULL)
goto errout;
- hdr = RTA_DATA(tb[TCA_EM_META_HDR-1]);
+ hdr = nla_data(tb[TCA_EM_META_HDR]);
if (TCF_META_TYPE(hdr->left.kind) != TCF_META_TYPE(hdr->right.kind) ||
TCF_META_TYPE(hdr->left.kind) > TCF_META_TYPE_MAX ||
@@ -781,8 +785,8 @@ static int em_meta_change(struct tcf_proto *tp, void *data, int len,
goto errout;
}
- if (meta_change_data(&meta->lvalue, tb[TCA_EM_META_LVALUE-1]) < 0 ||
- meta_change_data(&meta->rvalue, tb[TCA_EM_META_RVALUE-1]) < 0)
+ if (meta_change_data(&meta->lvalue, tb[TCA_EM_META_LVALUE]) < 0 ||
+ meta_change_data(&meta->rvalue, tb[TCA_EM_META_RVALUE]) < 0)
goto errout;
m->datalen = sizeof(*meta);
@@ -811,16 +815,16 @@ static int em_meta_dump(struct sk_buff *skb, struct tcf_ematch *em)
memcpy(&hdr.left, &meta->lvalue.hdr, sizeof(hdr.left));
memcpy(&hdr.right, &meta->rvalue.hdr, sizeof(hdr.right));
- RTA_PUT(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr);
+ NLA_PUT(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr);
ops = meta_type_ops(&meta->lvalue);
if (ops->dump(skb, &meta->lvalue, TCA_EM_META_LVALUE) < 0 ||
ops->dump(skb, &meta->rvalue, TCA_EM_META_RVALUE) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
return 0;
-rtattr_failure:
+nla_put_failure:
return -1;
}
diff --git a/net/sched/em_text.c b/net/sched/em_text.c
index d5cd86e..853c5ea 100644
--- a/net/sched/em_text.c
+++ b/net/sched/em_text.c
@@ -118,11 +118,14 @@ static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m)
conf.pattern_len = textsearch_get_pattern_len(tm->config);
conf.pad = 0;
- RTA_PUT_NOHDR(skb, sizeof(conf), &conf);
- RTA_APPEND(skb, conf.pattern_len, textsearch_get_pattern(tm->config));
+ if (nla_put_nohdr(skb, sizeof(conf), &conf) < 0)
+ goto nla_put_failure;
+ if (nla_append(skb, conf.pattern_len,
+ textsearch_get_pattern(tm->config)) < 0)
+ goto nla_put_failure;
return 0;
-rtattr_failure:
+nla_put_failure:
return -1;
}
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index f3a104e..74ff918 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -141,6 +141,7 @@ errout:
write_unlock(&ematch_mod_lock);
return err;
}
+EXPORT_SYMBOL(tcf_em_register);
/**
* tcf_em_unregister - unregster and extended match
@@ -171,6 +172,7 @@ out:
write_unlock(&ematch_mod_lock);
return err;
}
+EXPORT_SYMBOL(tcf_em_unregister);
static inline struct tcf_ematch * tcf_em_get_match(struct tcf_ematch_tree *tree,
int index)
@@ -181,11 +183,11 @@ static inline struct tcf_ematch * tcf_em_get_match(struct tcf_ematch_tree *tree,
static int tcf_em_validate(struct tcf_proto *tp,
struct tcf_ematch_tree_hdr *tree_hdr,
- struct tcf_ematch *em, struct rtattr *rta, int idx)
+ struct tcf_ematch *em, struct nlattr *nla, int idx)
{
int err = -EINVAL;
- struct tcf_ematch_hdr *em_hdr = RTA_DATA(rta);
- int data_len = RTA_PAYLOAD(rta) - sizeof(*em_hdr);
+ struct tcf_ematch_hdr *em_hdr = nla_data(nla);
+ int data_len = nla_len(nla) - sizeof(*em_hdr);
void *data = (void *) em_hdr + sizeof(*em_hdr);
if (!TCF_EM_REL_VALID(em_hdr->flags))
@@ -280,15 +282,20 @@ errout:
return err;
}
+static const struct nla_policy em_policy[TCA_EMATCH_TREE_MAX + 1] = {
+ [TCA_EMATCH_TREE_HDR] = { .len = sizeof(struct tcf_ematch_tree_hdr) },
+ [TCA_EMATCH_TREE_LIST] = { .type = NLA_NESTED },
+};
+
/**
* tcf_em_tree_validate - validate ematch config TLV and build ematch tree
*
* @tp: classifier kind handle
- * @rta: ematch tree configuration TLV
+ * @nla: ematch tree configuration TLV
* @tree: destination ematch tree variable to store the resulting
* ematch tree.
*
- * This function validates the given configuration TLV @rta and builds an
+ * This function validates the given configuration TLV @nla and builds an
* ematch tree in @tree. The resulting tree must later be copied into
* the private classifier data using tcf_em_tree_change(). You MUST NOT
* provide the ematch tree variable of the private classifier data directly,
@@ -296,45 +303,43 @@ errout:
*
* Returns a negative error code if the configuration TLV contains errors.
*/
-int tcf_em_tree_validate(struct tcf_proto *tp, struct rtattr *rta,
+int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
struct tcf_ematch_tree *tree)
{
- int idx, list_len, matches_len, err = -EINVAL;
- struct rtattr *tb[TCA_EMATCH_TREE_MAX];
- struct rtattr *rt_match, *rt_hdr, *rt_list;
+ int idx, list_len, matches_len, err;
+ struct nlattr *tb[TCA_EMATCH_TREE_MAX + 1];
+ struct nlattr *rt_match, *rt_hdr, *rt_list;
struct tcf_ematch_tree_hdr *tree_hdr;
struct tcf_ematch *em;
- if (!rta) {
+ if (!nla) {
memset(tree, 0, sizeof(*tree));
return 0;
}
- if (rtattr_parse_nested(tb, TCA_EMATCH_TREE_MAX, rta) < 0)
+ err = nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, nla, em_policy);
+ if (err < 0)
goto errout;
- rt_hdr = tb[TCA_EMATCH_TREE_HDR-1];
- rt_list = tb[TCA_EMATCH_TREE_LIST-1];
+ err = -EINVAL;
+ rt_hdr = tb[TCA_EMATCH_TREE_HDR];
+ rt_list = tb[TCA_EMATCH_TREE_LIST];
if (rt_hdr == NULL || rt_list == NULL)
goto errout;
- if (RTA_PAYLOAD(rt_hdr) < sizeof(*tree_hdr) ||
- RTA_PAYLOAD(rt_list) < sizeof(*rt_match))
- goto errout;
-
- tree_hdr = RTA_DATA(rt_hdr);
+ tree_hdr = nla_data(rt_hdr);
memcpy(&tree->hdr, tree_hdr, sizeof(*tree_hdr));
- rt_match = RTA_DATA(rt_list);
- list_len = RTA_PAYLOAD(rt_list);
+ rt_match = nla_data(rt_list);
+ list_len = nla_len(rt_list);
matches_len = tree_hdr->nmatches * sizeof(*em);
tree->matches = kzalloc(matches_len, GFP_KERNEL);
if (tree->matches == NULL)
goto errout;
- /* We do not use rtattr_parse_nested here because the maximum
+ /* We do not use nla_parse_nested here because the maximum
* number of attributes is unknown. This saves us the allocation
* for a tb buffer which would serve no purpose at all.
*
@@ -342,16 +347,16 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct rtattr *rta,
* provided, their type must be incremental from 1 to n. Even
* if it does not serve any real purpose, a failure of sticking
* to this policy will result in parsing failure. */
- for (idx = 0; RTA_OK(rt_match, list_len); idx++) {
+ for (idx = 0; nla_ok(rt_match, list_len); idx++) {
err = -EINVAL;
- if (rt_match->rta_type != (idx + 1))
+ if (rt_match->nla_type != (idx + 1))
goto errout_abort;
if (idx >= tree_hdr->nmatches)
goto errout_abort;
- if (RTA_PAYLOAD(rt_match) < sizeof(struct tcf_ematch_hdr))
+ if (nla_len(rt_match) < sizeof(struct tcf_ematch_hdr))
goto errout_abort;
em = tcf_em_get_match(tree, idx);
@@ -360,7 +365,7 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct rtattr *rta,
if (err < 0)
goto errout_abort;
- rt_match = RTA_NEXT(rt_match, list_len);
+ rt_match = nla_next(rt_match, &list_len);
}
/* Check if the number of matches provided by userspace actually
@@ -380,6 +385,7 @@ errout_abort:
tcf_em_tree_destroy(tp, tree);
return err;
}
+EXPORT_SYMBOL(tcf_em_tree_validate);
/**
* tcf_em_tree_destroy - destroy an ematch tree
@@ -413,6 +419,7 @@ void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree)
tree->hdr.nmatches = 0;
kfree(tree->matches);
}
+EXPORT_SYMBOL(tcf_em_tree_destroy);
/**
* tcf_em_tree_dump - dump ematch tree into a rtnl message
@@ -430,18 +437,22 @@ int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv)
{
int i;
u8 *tail;
- struct rtattr *top_start = (struct rtattr *)skb_tail_pointer(skb);
- struct rtattr *list_start;
+ struct nlattr *top_start;
+ struct nlattr *list_start;
+
+ top_start = nla_nest_start(skb, tlv);
+ if (top_start == NULL)
+ goto nla_put_failure;
- RTA_PUT(skb, tlv, 0, NULL);
- RTA_PUT(skb, TCA_EMATCH_TREE_HDR, sizeof(tree->hdr), &tree->hdr);
+ NLA_PUT(skb, TCA_EMATCH_TREE_HDR, sizeof(tree->hdr), &tree->hdr);
- list_start = (struct rtattr *)skb_tail_pointer(skb);
- RTA_PUT(skb, TCA_EMATCH_TREE_LIST, 0, NULL);
+ list_start = nla_nest_start(skb, TCA_EMATCH_TREE_LIST);
+ if (list_start == NULL)
+ goto nla_put_failure;
tail = skb_tail_pointer(skb);
for (i = 0; i < tree->hdr.nmatches; i++) {
- struct rtattr *match_start = (struct rtattr *)tail;
+ struct nlattr *match_start = (struct nlattr *)tail;
struct tcf_ematch *em = tcf_em_get_match(tree, i);
struct tcf_ematch_hdr em_hdr = {
.kind = em->ops ? em->ops->kind : TCF_EM_CONTAINER,
@@ -449,29 +460,30 @@ int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv)
.flags = em->flags
};
- RTA_PUT(skb, i+1, sizeof(em_hdr), &em_hdr);
+ NLA_PUT(skb, i+1, sizeof(em_hdr), &em_hdr);
if (em->ops && em->ops->dump) {
if (em->ops->dump(skb, em) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
} else if (tcf_em_is_container(em) || tcf_em_is_simple(em)) {
u32 u = em->data;
- RTA_PUT_NOHDR(skb, sizeof(u), &u);
+ nla_put_nohdr(skb, sizeof(u), &u);
} else if (em->datalen > 0)
- RTA_PUT_NOHDR(skb, em->datalen, (void *) em->data);
+ nla_put_nohdr(skb, em->datalen, (void *) em->data);
tail = skb_tail_pointer(skb);
- match_start->rta_len = tail - (u8 *)match_start;
+ match_start->nla_len = tail - (u8 *)match_start;
}
- list_start->rta_len = tail - (u8 *)list_start;
- top_start->rta_len = tail - (u8 *)top_start;
+ nla_nest_end(skb, list_start);
+ nla_nest_end(skb, top_start);
return 0;
-rtattr_failure:
+nla_put_failure:
return -1;
}
+EXPORT_SYMBOL(tcf_em_tree_dump);
static inline int tcf_em_match(struct sk_buff *skb, struct tcf_ematch *em,
struct tcf_pkt_info *info)
@@ -529,10 +541,4 @@ stack_overflow:
printk("Local stack overflow, increase NET_EMATCH_STACK\n");
return -1;
}
-
-EXPORT_SYMBOL(tcf_em_register);
-EXPORT_SYMBOL(tcf_em_unregister);
-EXPORT_SYMBOL(tcf_em_tree_validate);
-EXPORT_SYMBOL(tcf_em_tree_destroy);
-EXPORT_SYMBOL(tcf_em_tree_dump);
EXPORT_SYMBOL(__tcf_em_tree_match);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 8ae137e..7e3c048 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -29,6 +29,7 @@
#include <linux/hrtimer.h>
#include <net/net_namespace.h>
+#include <net/sock.h>
#include <net/netlink.h>
#include <net/pkt_sched.h>
@@ -157,6 +158,7 @@ out:
write_unlock(&qdisc_mod_lock);
return rc;
}
+EXPORT_SYMBOL(register_qdisc);
int unregister_qdisc(struct Qdisc_ops *qops)
{
@@ -175,6 +177,7 @@ int unregister_qdisc(struct Qdisc_ops *qops)
write_unlock(&qdisc_mod_lock);
return err;
}
+EXPORT_SYMBOL(unregister_qdisc);
/* We know handle. Find qdisc among all qdisc's attached to device
(root qdisc, all its children, children of children etc.)
@@ -195,7 +198,7 @@ static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
{
unsigned long cl;
struct Qdisc *leaf;
- struct Qdisc_class_ops *cops = p->ops->cl_ops;
+ const struct Qdisc_class_ops *cops = p->ops->cl_ops;
if (cops == NULL)
return NULL;
@@ -210,14 +213,14 @@ static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
/* Find queueing discipline by name */
-static struct Qdisc_ops *qdisc_lookup_ops(struct rtattr *kind)
+static struct Qdisc_ops *qdisc_lookup_ops(struct nlattr *kind)
{
struct Qdisc_ops *q = NULL;
if (kind) {
read_lock(&qdisc_mod_lock);
for (q = qdisc_base; q; q = q->next) {
- if (rtattr_strcmp(kind, q->id) == 0) {
+ if (nla_strcmp(kind, q->id) == 0) {
if (!try_module_get(q->owner))
q = NULL;
break;
@@ -230,7 +233,7 @@ static struct Qdisc_ops *qdisc_lookup_ops(struct rtattr *kind)
static struct qdisc_rate_table *qdisc_rtab_list;
-struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *tab)
+struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *tab)
{
struct qdisc_rate_table *rtab;
@@ -241,19 +244,21 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *ta
}
}
- if (tab == NULL || r->rate == 0 || r->cell_log == 0 || RTA_PAYLOAD(tab) != 1024)
+ if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
+ nla_len(tab) != TC_RTAB_SIZE)
return NULL;
rtab = kmalloc(sizeof(*rtab), GFP_KERNEL);
if (rtab) {
rtab->rate = *r;
rtab->refcnt = 1;
- memcpy(rtab->data, RTA_DATA(tab), 1024);
+ memcpy(rtab->data, nla_data(tab), 1024);
rtab->next = qdisc_rtab_list;
qdisc_rtab_list = rtab;
}
return rtab;
}
+EXPORT_SYMBOL(qdisc_get_rtab);
void qdisc_put_rtab(struct qdisc_rate_table *tab)
{
@@ -270,6 +275,7 @@ void qdisc_put_rtab(struct qdisc_rate_table *tab)
}
}
}
+EXPORT_SYMBOL(qdisc_put_rtab);
static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
{
@@ -373,7 +379,7 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
{
- struct Qdisc_class_ops *cops;
+ const struct Qdisc_class_ops *cops;
unsigned long cl;
u32 parentid;
@@ -417,7 +423,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
*old = dev_graft_qdisc(dev, new);
}
} else {
- struct Qdisc_class_ops *cops = parent->ops->cl_ops;
+ const struct Qdisc_class_ops *cops = parent->ops->cl_ops;
err = -EINVAL;
@@ -440,10 +446,10 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
static struct Qdisc *
qdisc_create(struct net_device *dev, u32 parent, u32 handle,
- struct rtattr **tca, int *errp)
+ struct nlattr **tca, int *errp)
{
int err;
- struct rtattr *kind = tca[TCA_KIND-1];
+ struct nlattr *kind = tca[TCA_KIND];
struct Qdisc *sch;
struct Qdisc_ops *ops;
@@ -451,7 +457,7 @@ qdisc_create(struct net_device *dev, u32 parent, u32 handle,
#ifdef CONFIG_KMOD
if (ops == NULL && kind != NULL) {
char name[IFNAMSIZ];
- if (rtattr_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
+ if (nla_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
/* We dropped the RTNL semaphore in order to
* perform the module load. So, even if we
* succeeded in loading the module we have to
@@ -504,11 +510,11 @@ qdisc_create(struct net_device *dev, u32 parent, u32 handle,
sch->handle = handle;
- if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
- if (tca[TCA_RATE-1]) {
+ if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS])) == 0) {
+ if (tca[TCA_RATE]) {
err = gen_new_estimator(&sch->bstats, &sch->rate_est,
sch->stats_lock,
- tca[TCA_RATE-1]);
+ tca[TCA_RATE]);
if (err) {
/*
* Any broken qdiscs that would require
@@ -536,20 +542,20 @@ err_out:
return NULL;
}
-static int qdisc_change(struct Qdisc *sch, struct rtattr **tca)
+static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
{
- if (tca[TCA_OPTIONS-1]) {
+ if (tca[TCA_OPTIONS]) {
int err;
if (sch->ops->change == NULL)
return -EINVAL;
- err = sch->ops->change(sch, tca[TCA_OPTIONS-1]);
+ err = sch->ops->change(sch, tca[TCA_OPTIONS]);
if (err)
return err;
}
- if (tca[TCA_RATE-1])
+ if (tca[TCA_RATE])
gen_replace_estimator(&sch->bstats, &sch->rate_est,
- sch->stats_lock, tca[TCA_RATE-1]);
+ sch->stats_lock, tca[TCA_RATE]);
return 0;
}
@@ -581,7 +587,7 @@ static int
check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w)
{
struct Qdisc *leaf;
- struct Qdisc_class_ops *cops = q->ops->cl_ops;
+ const struct Qdisc_class_ops *cops = q->ops->cl_ops;
struct check_loop_arg *arg = (struct check_loop_arg *)w;
leaf = cops->leaf(q, cl);
@@ -599,17 +605,25 @@ check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w)
static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
+ struct net *net = skb->sk->sk_net;
struct tcmsg *tcm = NLMSG_DATA(n);
- struct rtattr **tca = arg;
+ struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev;
u32 clid = tcm->tcm_parent;
struct Qdisc *q = NULL;
struct Qdisc *p = NULL;
int err;
+ if (net != &init_net)
+ return -EINVAL;
+
if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
return -ENODEV;
+ err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
+ if (err < 0)
+ return err;
+
if (clid) {
if (clid != TC_H_ROOT) {
if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {
@@ -632,7 +646,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
return -ENOENT;
}
- if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], q->ops->id))
+ if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id))
return -EINVAL;
if (n->nlmsg_type == RTM_DELQDISC) {
@@ -660,23 +674,30 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
+ struct net *net = skb->sk->sk_net;
struct tcmsg *tcm;
- struct rtattr **tca;
+ struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev;
u32 clid;
struct Qdisc *q, *p;
int err;
+ if (net != &init_net)
+ return -EINVAL;
+
replay:
/* Reinit, just in case something touches this. */
tcm = NLMSG_DATA(n);
- tca = arg;
clid = tcm->tcm_parent;
q = p = NULL;
if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
return -ENODEV;
+ err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
+ if (err < 0)
+ return err;
+
if (clid) {
if (clid != TC_H_ROOT) {
if (clid != TC_H_INGRESS) {
@@ -704,7 +725,7 @@ replay:
goto create_n_graft;
if (n->nlmsg_flags&NLM_F_EXCL)
return -EEXIST;
- if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], q->ops->id))
+ if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id))
return -EINVAL;
if (q == p ||
(p && check_loop(q, p, 0)))
@@ -737,8 +758,8 @@ replay:
if ((n->nlmsg_flags&NLM_F_CREATE) &&
(n->nlmsg_flags&NLM_F_REPLACE) &&
((n->nlmsg_flags&NLM_F_EXCL) ||
- (tca[TCA_KIND-1] &&
- rtattr_strcmp(tca[TCA_KIND-1], q->ops->id))))
+ (tca[TCA_KIND] &&
+ nla_strcmp(tca[TCA_KIND], q->ops->id))))
goto create_n_graft;
}
}
@@ -753,7 +774,7 @@ replay:
return -ENOENT;
if (n->nlmsg_flags&NLM_F_EXCL)
return -EEXIST;
- if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], q->ops->id))
+ if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id))
return -EINVAL;
err = qdisc_change(q, tca);
if (err == 0)
@@ -814,31 +835,31 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
tcm->tcm_parent = clid;
tcm->tcm_handle = q->handle;
tcm->tcm_info = atomic_read(&q->refcnt);
- RTA_PUT(skb, TCA_KIND, IFNAMSIZ, q->ops->id);
+ NLA_PUT_STRING(skb, TCA_KIND, q->ops->id);
if (q->ops->dump && q->ops->dump(q, skb) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
q->qstats.qlen = q->q.qlen;
if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
TCA_XSTATS, q->stats_lock, &d) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
if (q->ops->dump_stats && q->ops->dump_stats(q, &d) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
if (gnet_stats_copy_basic(&d, &q->bstats) < 0 ||
gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 ||
gnet_stats_copy_queue(&d, &q->qstats) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
if (gnet_stats_finish_copy(&d) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
return skb->len;
nlmsg_failure:
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -863,7 +884,7 @@ static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n,
}
if (skb->len)
- return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
err_out:
kfree_skb(skb);
@@ -872,11 +893,15 @@ err_out:
static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct net *net = skb->sk->sk_net;
int idx, q_idx;
int s_idx, s_q_idx;
struct net_device *dev;
struct Qdisc *q;
+ if (net != &init_net)
+ return 0;
+
s_idx = cb->args[0];
s_q_idx = q_idx = cb->args[1];
read_lock(&dev_base_lock);
@@ -920,11 +945,12 @@ done:
static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
+ struct net *net = skb->sk->sk_net;
struct tcmsg *tcm = NLMSG_DATA(n);
- struct rtattr **tca = arg;
+ struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev;
struct Qdisc *q = NULL;
- struct Qdisc_class_ops *cops;
+ const struct Qdisc_class_ops *cops;
unsigned long cl = 0;
unsigned long new_cl;
u32 pid = tcm->tcm_parent;
@@ -932,9 +958,16 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
u32 qid = TC_H_MAJ(clid);
int err;
+ if (net != &init_net)
+ return -EINVAL;
+
if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
return -ENODEV;
+ err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
+ if (err < 0)
+ return err;
+
/*
parent == TC_H_UNSPEC - unspecified parent.
parent == TC_H_ROOT - class is root, which has no parent.
@@ -1039,7 +1072,7 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
struct nlmsghdr *nlh;
unsigned char *b = skb_tail_pointer(skb);
struct gnet_dump d;
- struct Qdisc_class_ops *cl_ops = q->ops->cl_ops;
+ const struct Qdisc_class_ops *cl_ops = q->ops->cl_ops;
nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
tcm = NLMSG_DATA(nlh);
@@ -1048,25 +1081,25 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
tcm->tcm_parent = q->handle;
tcm->tcm_handle = q->handle;
tcm->tcm_info = 0;
- RTA_PUT(skb, TCA_KIND, IFNAMSIZ, q->ops->id);
+ NLA_PUT_STRING(skb, TCA_KIND, q->ops->id);
if (cl_ops->dump && cl_ops->dump(q, cl, skb, tcm) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
TCA_XSTATS, q->stats_lock, &d) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
if (cl_ops->dump_stats && cl_ops->dump_stats(q, cl, &d) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
if (gnet_stats_finish_copy(&d) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
return skb->len;
nlmsg_failure:
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -1086,7 +1119,7 @@ static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n,
return -EINVAL;
}
- return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
}
struct qdisc_dump_args
@@ -1106,6 +1139,7 @@ static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walk
static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct net *net = skb->sk->sk_net;
int t;
int s_t;
struct net_device *dev;
@@ -1113,6 +1147,9 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
struct tcmsg *tcm = (struct tcmsg*)NLMSG_DATA(cb->nlh);
struct qdisc_dump_args arg;
+ if (net != &init_net)
+ return 0;
+
if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
return 0;
if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
@@ -1268,8 +1305,3 @@ static int __init pktsched_init(void)
}
subsys_initcall(pktsched_init);
-
-EXPORT_SYMBOL(qdisc_get_rtab);
-EXPORT_SYMBOL(qdisc_put_rtab);
-EXPORT_SYMBOL(register_qdisc);
-EXPORT_SYMBOL(unregister_qdisc);
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index ddc4f2c..3352734 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -16,18 +16,6 @@
extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */
-#if 0 /* control */
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define DPRINTK(format,args...)
-#endif
-
-#if 0 /* data */
-#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define D2PRINTK(format,args...)
-#endif
-
/*
* The ATM queuing discipline provides a framework for invoking classifiers
* (aka "filters"), which in turn select classes of this queuing discipline.
@@ -49,7 +37,6 @@ extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */
* - should lock the flow while there is data in the queue (?)
*/
-#define PRIV(sch) qdisc_priv(sch)
#define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back))
struct atm_flow_data {
@@ -57,7 +44,7 @@ struct atm_flow_data {
struct tcf_proto *filter_list;
struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */
void (*old_pop)(struct atm_vcc *vcc,
- struct sk_buff * skb); /* chaining */
+ struct sk_buff *skb); /* chaining */
struct atm_qdisc_data *parent; /* parent qdisc */
struct socket *sock; /* for closing */
u32 classid; /* x:y type ID */
@@ -84,17 +71,17 @@ static int find_flow(struct atm_qdisc_data *qdisc, struct atm_flow_data *flow)
{
struct atm_flow_data *walk;
- DPRINTK("find_flow(qdisc %p,flow %p)\n", qdisc, flow);
+ pr_debug("find_flow(qdisc %p,flow %p)\n", qdisc, flow);
for (walk = qdisc->flows; walk; walk = walk->next)
if (walk == flow)
return 1;
- DPRINTK("find_flow: not found\n");
+ pr_debug("find_flow: not found\n");
return 0;
}
static inline struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow;
for (flow = p->flows; flow; flow = flow->next)
@@ -106,10 +93,10 @@ static inline struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid)
static int atm_tc_graft(struct Qdisc *sch, unsigned long arg,
struct Qdisc *new, struct Qdisc **old)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow = (struct atm_flow_data *)arg;
- DPRINTK("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",
+ pr_debug("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",
sch, p, flow, new, old);
if (!find_flow(p, flow))
return -EINVAL;
@@ -125,20 +112,20 @@ static struct Qdisc *atm_tc_leaf(struct Qdisc *sch, unsigned long cl)
{
struct atm_flow_data *flow = (struct atm_flow_data *)cl;
- DPRINTK("atm_tc_leaf(sch %p,flow %p)\n", sch, flow);
+ pr_debug("atm_tc_leaf(sch %p,flow %p)\n", sch, flow);
return flow ? flow->q : NULL;
}
static unsigned long atm_tc_get(struct Qdisc *sch, u32 classid)
{
- struct atm_qdisc_data *p __maybe_unused = PRIV(sch);
+ struct atm_qdisc_data *p __maybe_unused = qdisc_priv(sch);
struct atm_flow_data *flow;
- DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
+ pr_debug("atm_tc_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
flow = lookup_flow(sch, classid);
if (flow)
flow->ref++;
- DPRINTK("atm_tc_get: flow %p\n", flow);
+ pr_debug("atm_tc_get: flow %p\n", flow);
return (unsigned long)flow;
}
@@ -155,14 +142,14 @@ static unsigned long atm_tc_bind_filter(struct Qdisc *sch,
*/
static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow = (struct atm_flow_data *)cl;
struct atm_flow_data **prev;
- DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
+ pr_debug("atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
if (--flow->ref)
return;
- DPRINTK("atm_tc_put: destroying\n");
+ pr_debug("atm_tc_put: destroying\n");
for (prev = &p->flows; *prev; prev = &(*prev)->next)
if (*prev == flow)
break;
@@ -171,11 +158,11 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
return;
}
*prev = flow->next;
- DPRINTK("atm_tc_put: qdisc %p\n", flow->q);
+ pr_debug("atm_tc_put: qdisc %p\n", flow->q);
qdisc_destroy(flow->q);
tcf_destroy_chain(flow->filter_list);
if (flow->sock) {
- DPRINTK("atm_tc_put: f_count %d\n",
+ pr_debug("atm_tc_put: f_count %d\n",
file_count(flow->sock->file));
flow->vcc->pop = flow->old_pop;
sockfd_put(flow->sock);
@@ -194,7 +181,7 @@ static void sch_atm_pop(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct atm_qdisc_data *p = VCC2FLOW(vcc)->parent;
- D2PRINTK("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n", vcc, skb, p);
+ pr_debug("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n", vcc, skb, p);
VCC2FLOW(vcc)->old_pop(vcc, skb);
tasklet_schedule(&p->task);
}
@@ -208,19 +195,24 @@ static const u8 llc_oui_ip[] = {
0x08, 0x00
}; /* Ethertype IP (0800) */
+static const struct nla_policy atm_policy[TCA_ATM_MAX + 1] = {
+ [TCA_ATM_FD] = { .type = NLA_U32 },
+ [TCA_ATM_EXCESS] = { .type = NLA_U32 },
+};
+
static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
- struct rtattr **tca, unsigned long *arg)
+ struct nlattr **tca, unsigned long *arg)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow = (struct atm_flow_data *)*arg;
struct atm_flow_data *excess = NULL;
- struct rtattr *opt = tca[TCA_OPTIONS - 1];
- struct rtattr *tb[TCA_ATM_MAX];
+ struct nlattr *opt = tca[TCA_OPTIONS];
+ struct nlattr *tb[TCA_ATM_MAX + 1];
struct socket *sock;
int fd, error, hdr_len;
void *hdr;
- DPRINTK("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x,"
+ pr_debug("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x,"
"flow %p,opt %p)\n", sch, p, classid, parent, flow, opt);
/*
* The concept of parents doesn't apply for this qdisc.
@@ -236,34 +228,38 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
*/
if (flow)
return -EBUSY;
- if (opt == NULL || rtattr_parse_nested(tb, TCA_ATM_MAX, opt))
+ if (opt == NULL)
return -EINVAL;
- if (!tb[TCA_ATM_FD - 1] || RTA_PAYLOAD(tb[TCA_ATM_FD - 1]) < sizeof(fd))
+
+ error = nla_parse_nested(tb, TCA_ATM_MAX, opt, atm_policy);
+ if (error < 0)
+ return error;
+
+ if (!tb[TCA_ATM_FD])
return -EINVAL;
- fd = *(int *)RTA_DATA(tb[TCA_ATM_FD - 1]);
- DPRINTK("atm_tc_change: fd %d\n", fd);
- if (tb[TCA_ATM_HDR - 1]) {
- hdr_len = RTA_PAYLOAD(tb[TCA_ATM_HDR - 1]);
- hdr = RTA_DATA(tb[TCA_ATM_HDR - 1]);
+ fd = nla_get_u32(tb[TCA_ATM_FD]);
+ pr_debug("atm_tc_change: fd %d\n", fd);
+ if (tb[TCA_ATM_HDR]) {
+ hdr_len = nla_len(tb[TCA_ATM_HDR]);
+ hdr = nla_data(tb[TCA_ATM_HDR]);
} else {
hdr_len = RFC1483LLC_LEN;
hdr = NULL; /* default LLC/SNAP for IP */
}
- if (!tb[TCA_ATM_EXCESS - 1])
+ if (!tb[TCA_ATM_EXCESS])
excess = NULL;
else {
- if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS - 1]) != sizeof(u32))
- return -EINVAL;
excess = (struct atm_flow_data *)
- atm_tc_get(sch, *(u32 *)RTA_DATA(tb[TCA_ATM_EXCESS - 1]));
+ atm_tc_get(sch, nla_get_u32(tb[TCA_ATM_EXCESS]));
if (!excess)
return -ENOENT;
}
- DPRINTK("atm_tc_change: type %d, payload %d, hdr_len %d\n",
- opt->rta_type, RTA_PAYLOAD(opt), hdr_len);
- if (!(sock = sockfd_lookup(fd, &error)))
+ pr_debug("atm_tc_change: type %d, payload %d, hdr_len %d\n",
+ opt->nla_type, nla_len(opt), hdr_len);
+ sock = sockfd_lookup(fd, &error);
+ if (!sock)
return error; /* f_count++ */
- DPRINTK("atm_tc_change: f_count %d\n", file_count(sock->file));
+ pr_debug("atm_tc_change: f_count %d\n", file_count(sock->file));
if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) {
error = -EPROTOTYPE;
goto err_out;
@@ -272,7 +268,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
on vcc->send */
if (classid) {
if (TC_H_MAJ(classid ^ sch->handle)) {
- DPRINTK("atm_tc_change: classid mismatch\n");
+ pr_debug("atm_tc_change: classid mismatch\n");
error = -EINVAL;
goto err_out;
}
@@ -286,26 +282,28 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
for (i = 1; i < 0x8000; i++) {
classid = TC_H_MAKE(sch->handle, 0x8000 | i);
- if (!(cl = atm_tc_get(sch, classid)))
+ cl = atm_tc_get(sch, classid);
+ if (!cl)
break;
atm_tc_put(sch, cl);
}
}
- DPRINTK("atm_tc_change: new id %x\n", classid);
+ pr_debug("atm_tc_change: new id %x\n", classid);
flow = kzalloc(sizeof(struct atm_flow_data) + hdr_len, GFP_KERNEL);
- DPRINTK("atm_tc_change: flow %p\n", flow);
+ pr_debug("atm_tc_change: flow %p\n", flow);
if (!flow) {
error = -ENOBUFS;
goto err_out;
}
flow->filter_list = NULL;
- if (!(flow->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid)))
+ flow->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
+ if (!flow->q)
flow->q = &noop_qdisc;
- DPRINTK("atm_tc_change: qdisc %p\n", flow->q);
+ pr_debug("atm_tc_change: qdisc %p\n", flow->q);
flow->sock = sock;
flow->vcc = ATM_SD(sock); /* speedup */
flow->vcc->user_back = flow;
- DPRINTK("atm_tc_change: vcc %p\n", flow->vcc);
+ pr_debug("atm_tc_change: vcc %p\n", flow->vcc);
flow->old_pop = flow->vcc->pop;
flow->parent = p;
flow->vcc->pop = sch_atm_pop;
@@ -330,11 +328,11 @@ err_out:
static int atm_tc_delete(struct Qdisc *sch, unsigned long arg)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow = (struct atm_flow_data *)arg;
- DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
- if (!find_flow(PRIV(sch), flow))
+ pr_debug("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
+ if (!find_flow(qdisc_priv(sch), flow))
return -EINVAL;
if (flow->filter_list || flow == &p->link)
return -EBUSY;
@@ -354,10 +352,10 @@ static int atm_tc_delete(struct Qdisc *sch, unsigned long arg)
static void atm_tc_walk(struct Qdisc *sch, struct qdisc_walker *walker)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow;
- DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
+ pr_debug("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
if (walker->stop)
return;
for (flow = p->flows; flow; flow = flow->next) {
@@ -372,10 +370,10 @@ static void atm_tc_walk(struct Qdisc *sch, struct qdisc_walker *walker)
static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch, unsigned long cl)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow = (struct atm_flow_data *)cl;
- DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
+ pr_debug("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
return flow ? &flow->filter_list : &p->link.filter_list;
}
@@ -383,13 +381,13 @@ static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch, unsigned long cl)
static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow = NULL; /* @@@ */
struct tcf_result res;
int result;
int ret = NET_XMIT_POLICED;
- D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+ pr_debug("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
result = TC_POLICE_OK; /* be nice to gcc */
if (TC_H_MAJ(skb->priority) != sch->handle ||
!(flow = (struct atm_flow_data *)atm_tc_get(sch, skb->priority)))
@@ -430,7 +428,8 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
#endif
}
- if ((ret = flow->q->enqueue(skb, flow->q)) != 0) {
+ ret = flow->q->enqueue(skb, flow->q);
+ if (ret != 0) {
drop: __maybe_unused
sch->qstats.drops++;
if (flow)
@@ -468,11 +467,11 @@ drop: __maybe_unused
static void sch_atm_dequeue(unsigned long data)
{
struct Qdisc *sch = (struct Qdisc *)data;
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow;
struct sk_buff *skb;
- D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p);
+ pr_debug("sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p);
for (flow = p->link.next; flow; flow = flow->next)
/*
* If traffic is properly shaped, this won't generate nasty
@@ -483,7 +482,7 @@ static void sch_atm_dequeue(unsigned long data)
(void)flow->q->ops->requeue(skb, flow->q);
break;
}
- D2PRINTK("atm_tc_dequeue: sending on class %p\n", flow);
+ pr_debug("atm_tc_dequeue: sending on class %p\n", flow);
/* remove any LL header somebody else has attached */
skb_pull(skb, skb_network_offset(skb));
if (skb_headroom(skb) < flow->hdr_len) {
@@ -495,7 +494,7 @@ static void sch_atm_dequeue(unsigned long data)
continue;
skb = new;
}
- D2PRINTK("sch_atm_dequeue: ip %p, data %p\n",
+ pr_debug("sch_atm_dequeue: ip %p, data %p\n",
skb_network_header(skb), skb->data);
ATM_SKB(skb)->vcc = flow->vcc;
memcpy(skb_push(skb, flow->hdr_len), flow->hdr,
@@ -509,10 +508,10 @@ static void sch_atm_dequeue(unsigned long data)
static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct sk_buff *skb;
- D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p);
+ pr_debug("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p);
tasklet_schedule(&p->task);
skb = p->link.q->dequeue(p->link.q);
if (skb)
@@ -522,10 +521,10 @@ static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch)
static int atm_tc_requeue(struct sk_buff *skb, struct Qdisc *sch)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
int ret;
- D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+ pr_debug("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
ret = p->link.q->ops->requeue(skb, p->link.q);
if (!ret) {
sch->q.qlen++;
@@ -539,27 +538,27 @@ static int atm_tc_requeue(struct sk_buff *skb, struct Qdisc *sch)
static unsigned int atm_tc_drop(struct Qdisc *sch)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow;
unsigned int len;
- DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n", sch, p);
+ pr_debug("atm_tc_drop(sch %p,[qdisc %p])\n", sch, p);
for (flow = p->flows; flow; flow = flow->next)
if (flow->q->ops->drop && (len = flow->q->ops->drop(flow->q)))
return len;
return 0;
}
-static int atm_tc_init(struct Qdisc *sch, struct rtattr *opt)
+static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
- DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
+ pr_debug("atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
p->flows = &p->link;
- if (!(p->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
- sch->handle)))
+ p->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, sch->handle);
+ if (!p->link.q)
p->link.q = &noop_qdisc;
- DPRINTK("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
+ pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
p->link.filter_list = NULL;
p->link.vcc = NULL;
p->link.sock = NULL;
@@ -572,10 +571,10 @@ static int atm_tc_init(struct Qdisc *sch, struct rtattr *opt)
static void atm_tc_reset(struct Qdisc *sch)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow;
- DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p);
+ pr_debug("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p);
for (flow = p->flows; flow; flow = flow->next)
qdisc_reset(flow->q);
sch->q.qlen = 0;
@@ -583,10 +582,10 @@ static void atm_tc_reset(struct Qdisc *sch)
static void atm_tc_destroy(struct Qdisc *sch)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow;
- DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p);
+ pr_debug("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p);
/* races ? */
while ((flow = p->flows)) {
tcf_destroy_chain(flow->filter_list);
@@ -608,20 +607,22 @@ static void atm_tc_destroy(struct Qdisc *sch)
static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
struct sk_buff *skb, struct tcmsg *tcm)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p = qdisc_priv(sch);
struct atm_flow_data *flow = (struct atm_flow_data *)cl;
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
- DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n",
+ pr_debug("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n",
sch, p, flow, skb, tcm);
if (!find_flow(p, flow))
return -EINVAL;
tcm->tcm_handle = flow->classid;
tcm->tcm_info = flow->q->handle;
- rta = (struct rtattr *)b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
- RTA_PUT(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr);
+
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
+
+ NLA_PUT(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr);
if (flow->vcc) {
struct sockaddr_atmpvc pvc;
int state;
@@ -630,22 +631,21 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1;
pvc.sap_addr.vpi = flow->vcc->vpi;
pvc.sap_addr.vci = flow->vcc->vci;
- RTA_PUT(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc);
+ NLA_PUT(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc);
state = ATM_VF2VS(flow->vcc->flags);
- RTA_PUT(skb, TCA_ATM_STATE, sizeof(state), &state);
+ NLA_PUT_U32(skb, TCA_ATM_STATE, state);
}
if (flow->excess)
- RTA_PUT(skb, TCA_ATM_EXCESS, sizeof(u32), &flow->classid);
+ NLA_PUT_U32(skb, TCA_ATM_EXCESS, flow->classid);
else {
- static u32 zero;
-
- RTA_PUT(skb, TCA_ATM_EXCESS, sizeof(zero), &zero);
+ NLA_PUT_U32(skb, TCA_ATM_EXCESS, 0);
}
- rta->rta_len = skb_tail_pointer(skb) - b;
+
+ nla_nest_end(skb, nest);
return skb->len;
-rtattr_failure:
- nlmsg_trim(skb, b);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
return -1;
}
static int
@@ -668,7 +668,7 @@ static int atm_tc_dump(struct Qdisc *sch, struct sk_buff *skb)
return 0;
}
-static struct Qdisc_class_ops atm_class_ops = {
+static const struct Qdisc_class_ops atm_class_ops = {
.graft = atm_tc_graft,
.leaf = atm_tc_leaf,
.get = atm_tc_get,
@@ -683,7 +683,7 @@ static struct Qdisc_class_ops atm_class_ops = {
.dump_stats = atm_tc_dump_class_stats,
};
-static struct Qdisc_ops atm_qdisc_ops = {
+static struct Qdisc_ops atm_qdisc_ops __read_mostly = {
.cl_ops = &atm_class_ops,
.id = "atm",
.priv_size = sizeof(struct atm_qdisc_data),
diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c
index f914fc4..507fb48 100644
--- a/net/sched/sch_blackhole.c
+++ b/net/sched/sch_blackhole.c
@@ -28,7 +28,7 @@ static struct sk_buff *blackhole_dequeue(struct Qdisc *sch)
return NULL;
}
-static struct Qdisc_ops blackhole_qdisc_ops = {
+static struct Qdisc_ops blackhole_qdisc_ops __read_mostly = {
.id = "blackhole",
.priv_size = 0,
.enqueue = blackhole_enqueue,
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 4de3744..09969c1 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1377,24 +1377,33 @@ static int cbq_set_fopt(struct cbq_class *cl, struct tc_cbq_fopt *fopt)
return 0;
}
-static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
+static const struct nla_policy cbq_policy[TCA_CBQ_MAX + 1] = {
+ [TCA_CBQ_LSSOPT] = { .len = sizeof(struct tc_cbq_lssopt) },
+ [TCA_CBQ_WRROPT] = { .len = sizeof(struct tc_cbq_wrropt) },
+ [TCA_CBQ_FOPT] = { .len = sizeof(struct tc_cbq_fopt) },
+ [TCA_CBQ_OVL_STRATEGY] = { .len = sizeof(struct tc_cbq_ovl) },
+ [TCA_CBQ_RATE] = { .len = sizeof(struct tc_ratespec) },
+ [TCA_CBQ_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+ [TCA_CBQ_POLICE] = { .len = sizeof(struct tc_cbq_police) },
+};
+
+static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
{
struct cbq_sched_data *q = qdisc_priv(sch);
- struct rtattr *tb[TCA_CBQ_MAX];
+ struct nlattr *tb[TCA_CBQ_MAX + 1];
struct tc_ratespec *r;
+ int err;
- if (rtattr_parse_nested(tb, TCA_CBQ_MAX, opt) < 0 ||
- tb[TCA_CBQ_RTAB-1] == NULL || tb[TCA_CBQ_RATE-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_CBQ_RATE-1]) < sizeof(struct tc_ratespec))
- return -EINVAL;
+ err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
+ if (err < 0)
+ return err;
- if (tb[TCA_CBQ_LSSOPT-1] &&
- RTA_PAYLOAD(tb[TCA_CBQ_LSSOPT-1]) < sizeof(struct tc_cbq_lssopt))
+ if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL)
return -EINVAL;
- r = RTA_DATA(tb[TCA_CBQ_RATE-1]);
+ r = nla_data(tb[TCA_CBQ_RATE]);
- if ((q->link.R_tab = qdisc_get_rtab(r, tb[TCA_CBQ_RTAB-1])) == NULL)
+ if ((q->link.R_tab = qdisc_get_rtab(r, tb[TCA_CBQ_RTAB])) == NULL)
return -EINVAL;
q->link.refcnt = 1;
@@ -1427,8 +1436,8 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
cbq_link_class(&q->link);
- if (tb[TCA_CBQ_LSSOPT-1])
- cbq_set_lss(&q->link, RTA_DATA(tb[TCA_CBQ_LSSOPT-1]));
+ if (tb[TCA_CBQ_LSSOPT])
+ cbq_set_lss(&q->link, nla_data(tb[TCA_CBQ_LSSOPT]));
cbq_addprio(q, &q->link);
return 0;
@@ -1438,10 +1447,10 @@ static __inline__ int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl)
{
unsigned char *b = skb_tail_pointer(skb);
- RTA_PUT(skb, TCA_CBQ_RATE, sizeof(cl->R_tab->rate), &cl->R_tab->rate);
+ NLA_PUT(skb, TCA_CBQ_RATE, sizeof(cl->R_tab->rate), &cl->R_tab->rate);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -1463,10 +1472,10 @@ static __inline__ int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl)
opt.minidle = (u32)(-cl->minidle);
opt.offtime = cl->offtime;
opt.change = ~0;
- RTA_PUT(skb, TCA_CBQ_LSSOPT, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_CBQ_LSSOPT, sizeof(opt), &opt);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -1481,10 +1490,10 @@ static __inline__ int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl)
opt.priority = cl->priority+1;
opt.cpriority = cl->cpriority+1;
opt.weight = cl->weight;
- RTA_PUT(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -1498,10 +1507,10 @@ static __inline__ int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl)
opt.priority2 = cl->priority2+1;
opt.pad = 0;
opt.penalty = cl->penalty;
- RTA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -1515,11 +1524,11 @@ static __inline__ int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl)
opt.split = cl->split ? cl->split->classid : 0;
opt.defmap = cl->defmap;
opt.defchange = ~0;
- RTA_PUT(skb, TCA_CBQ_FOPT, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_CBQ_FOPT, sizeof(opt), &opt);
}
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -1534,11 +1543,11 @@ static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl)
opt.police = cl->police;
opt.__res1 = 0;
opt.__res2 = 0;
- RTA_PUT(skb, TCA_CBQ_POLICE, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_CBQ_POLICE, sizeof(opt), &opt);
}
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -1561,18 +1570,18 @@ static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl)
static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct cbq_sched_data *q = qdisc_priv(sch);
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
- rta = (struct rtattr*)b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
if (cbq_dump_attr(skb, &q->link) < 0)
- goto rtattr_failure;
- rta->rta_len = skb_tail_pointer(skb) - b;
+ goto nla_put_failure;
+ nla_nest_end(skb, nest);
return skb->len;
-rtattr_failure:
- nlmsg_trim(skb, b);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
return -1;
}
@@ -1590,8 +1599,7 @@ cbq_dump_class(struct Qdisc *sch, unsigned long arg,
struct sk_buff *skb, struct tcmsg *tcm)
{
struct cbq_class *cl = (struct cbq_class*)arg;
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
if (cl->tparent)
tcm->tcm_parent = cl->tparent->classid;
@@ -1600,15 +1608,16 @@ cbq_dump_class(struct Qdisc *sch, unsigned long arg,
tcm->tcm_handle = cl->classid;
tcm->tcm_info = cl->q->handle;
- rta = (struct rtattr*)b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
if (cbq_dump_attr(skb, cl) < 0)
- goto rtattr_failure;
- rta->rta_len = skb_tail_pointer(skb) - b;
+ goto nla_put_failure;
+ nla_nest_end(skb, nest);
return skb->len;
-rtattr_failure:
- nlmsg_trim(skb, b);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
return -1;
}
@@ -1753,45 +1762,23 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg)
}
static int
-cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **tca,
+cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **tca,
unsigned long *arg)
{
int err;
struct cbq_sched_data *q = qdisc_priv(sch);
struct cbq_class *cl = (struct cbq_class*)*arg;
- struct rtattr *opt = tca[TCA_OPTIONS-1];
- struct rtattr *tb[TCA_CBQ_MAX];
+ struct nlattr *opt = tca[TCA_OPTIONS];
+ struct nlattr *tb[TCA_CBQ_MAX + 1];
struct cbq_class *parent;
struct qdisc_rate_table *rtab = NULL;
- if (opt==NULL || rtattr_parse_nested(tb, TCA_CBQ_MAX, opt))
+ if (opt == NULL)
return -EINVAL;
- if (tb[TCA_CBQ_OVL_STRATEGY-1] &&
- RTA_PAYLOAD(tb[TCA_CBQ_OVL_STRATEGY-1]) < sizeof(struct tc_cbq_ovl))
- return -EINVAL;
-
- if (tb[TCA_CBQ_FOPT-1] &&
- RTA_PAYLOAD(tb[TCA_CBQ_FOPT-1]) < sizeof(struct tc_cbq_fopt))
- return -EINVAL;
-
- if (tb[TCA_CBQ_RATE-1] &&
- RTA_PAYLOAD(tb[TCA_CBQ_RATE-1]) < sizeof(struct tc_ratespec))
- return -EINVAL;
-
- if (tb[TCA_CBQ_LSSOPT-1] &&
- RTA_PAYLOAD(tb[TCA_CBQ_LSSOPT-1]) < sizeof(struct tc_cbq_lssopt))
- return -EINVAL;
-
- if (tb[TCA_CBQ_WRROPT-1] &&
- RTA_PAYLOAD(tb[TCA_CBQ_WRROPT-1]) < sizeof(struct tc_cbq_wrropt))
- return -EINVAL;
-
-#ifdef CONFIG_NET_CLS_ACT
- if (tb[TCA_CBQ_POLICE-1] &&
- RTA_PAYLOAD(tb[TCA_CBQ_POLICE-1]) < sizeof(struct tc_cbq_police))
- return -EINVAL;
-#endif
+ err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
+ if (err < 0)
+ return err;
if (cl) {
/* Check parent */
@@ -1802,8 +1789,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
return -EINVAL;
}
- if (tb[TCA_CBQ_RATE-1]) {
- rtab = qdisc_get_rtab(RTA_DATA(tb[TCA_CBQ_RATE-1]), tb[TCA_CBQ_RTAB-1]);
+ if (tb[TCA_CBQ_RATE]) {
+ rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB]);
if (rtab == NULL)
return -EINVAL;
}
@@ -1819,45 +1806,45 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
qdisc_put_rtab(rtab);
}
- if (tb[TCA_CBQ_LSSOPT-1])
- cbq_set_lss(cl, RTA_DATA(tb[TCA_CBQ_LSSOPT-1]));
+ if (tb[TCA_CBQ_LSSOPT])
+ cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT]));
- if (tb[TCA_CBQ_WRROPT-1]) {
+ if (tb[TCA_CBQ_WRROPT]) {
cbq_rmprio(q, cl);
- cbq_set_wrr(cl, RTA_DATA(tb[TCA_CBQ_WRROPT-1]));
+ cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT]));
}
- if (tb[TCA_CBQ_OVL_STRATEGY-1])
- cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1]));
+ if (tb[TCA_CBQ_OVL_STRATEGY])
+ cbq_set_overlimit(cl, nla_data(tb[TCA_CBQ_OVL_STRATEGY]));
#ifdef CONFIG_NET_CLS_ACT
- if (tb[TCA_CBQ_POLICE-1])
- cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1]));
+ if (tb[TCA_CBQ_POLICE])
+ cbq_set_police(cl, nla_data(tb[TCA_CBQ_POLICE]));
#endif
- if (tb[TCA_CBQ_FOPT-1])
- cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1]));
+ if (tb[TCA_CBQ_FOPT])
+ cbq_set_fopt(cl, nla_data(tb[TCA_CBQ_FOPT]));
if (cl->q->q.qlen)
cbq_activate_class(cl);
sch_tree_unlock(sch);
- if (tca[TCA_RATE-1])
+ if (tca[TCA_RATE])
gen_replace_estimator(&cl->bstats, &cl->rate_est,
&sch->dev->queue_lock,
- tca[TCA_RATE-1]);
+ tca[TCA_RATE]);
return 0;
}
if (parentid == TC_H_ROOT)
return -EINVAL;
- if (tb[TCA_CBQ_WRROPT-1] == NULL || tb[TCA_CBQ_RATE-1] == NULL ||
- tb[TCA_CBQ_LSSOPT-1] == NULL)
+ if (tb[TCA_CBQ_WRROPT] == NULL || tb[TCA_CBQ_RATE] == NULL ||
+ tb[TCA_CBQ_LSSOPT] == NULL)
return -EINVAL;
- rtab = qdisc_get_rtab(RTA_DATA(tb[TCA_CBQ_RATE-1]), tb[TCA_CBQ_RTAB-1]);
+ rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB]);
if (rtab == NULL)
return -EINVAL;
@@ -1912,8 +1899,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
cl->share = cl->tparent;
cbq_adjust_levels(parent);
cl->minidle = -0x7FFFFFFF;
- cbq_set_lss(cl, RTA_DATA(tb[TCA_CBQ_LSSOPT-1]));
- cbq_set_wrr(cl, RTA_DATA(tb[TCA_CBQ_WRROPT-1]));
+ cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT]));
+ cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT]));
if (cl->ewma_log==0)
cl->ewma_log = q->link.ewma_log;
if (cl->maxidle==0)
@@ -1921,19 +1908,19 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
if (cl->avpkt==0)
cl->avpkt = q->link.avpkt;
cl->overlimit = cbq_ovl_classic;
- if (tb[TCA_CBQ_OVL_STRATEGY-1])
- cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1]));
+ if (tb[TCA_CBQ_OVL_STRATEGY])
+ cbq_set_overlimit(cl, nla_data(tb[TCA_CBQ_OVL_STRATEGY]));
#ifdef CONFIG_NET_CLS_ACT
- if (tb[TCA_CBQ_POLICE-1])
- cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1]));
+ if (tb[TCA_CBQ_POLICE])
+ cbq_set_police(cl, nla_data(tb[TCA_CBQ_POLICE]));
#endif
- if (tb[TCA_CBQ_FOPT-1])
- cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1]));
+ if (tb[TCA_CBQ_FOPT])
+ cbq_set_fopt(cl, nla_data(tb[TCA_CBQ_FOPT]));
sch_tree_unlock(sch);
- if (tca[TCA_RATE-1])
+ if (tca[TCA_RATE])
gen_new_estimator(&cl->bstats, &cl->rate_est,
- &sch->dev->queue_lock, tca[TCA_RATE-1]);
+ &sch->dev->queue_lock, tca[TCA_RATE]);
*arg = (unsigned long)cl;
return 0;
@@ -2045,7 +2032,7 @@ static void cbq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
}
}
-static struct Qdisc_class_ops cbq_class_ops = {
+static const struct Qdisc_class_ops cbq_class_ops = {
.graft = cbq_graft,
.leaf = cbq_leaf,
.qlen_notify = cbq_qlen_notify,
@@ -2061,7 +2048,7 @@ static struct Qdisc_class_ops cbq_class_ops = {
.dump_stats = cbq_dump_class_stats,
};
-static struct Qdisc_ops cbq_qdisc_ops = {
+static struct Qdisc_ops cbq_qdisc_ops __read_mostly = {
.next = NULL,
.cl_ops = &cbq_class_ops,
.id = "cbq",
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 60f8919..0df911f 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -10,28 +10,12 @@
#include <linux/errno.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
+#include <linux/bitops.h>
#include <net/pkt_sched.h>
#include <net/dsfield.h>
#include <net/inet_ecn.h>
#include <asm/byteorder.h>
-
-#if 0 /* control */
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define DPRINTK(format,args...)
-#endif
-
-#if 0 /* data */
-#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define D2PRINTK(format,args...)
-#endif
-
-
-#define PRIV(sch) ((struct dsmark_qdisc_data *) qdisc_priv(sch))
-
-
/*
* classid class marking
* ------- ----- -------
@@ -60,17 +44,6 @@ struct dsmark_qdisc_data {
int set_tc_index;
};
-static inline int dsmark_valid_indices(u16 indices)
-{
- while (indices != 1) {
- if (indices & 1)
- return 0;
- indices >>= 1;
- }
-
- return 1;
-}
-
static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index)
{
return (index <= p->indices && index > 0);
@@ -81,9 +54,9 @@ static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index)
static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
struct Qdisc *new, struct Qdisc **old)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
- DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",
+ pr_debug("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",
sch, p, new, old);
if (new == NULL) {
@@ -104,13 +77,14 @@ static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
{
- return PRIV(sch)->q;
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
+ return p->q;
}
static unsigned long dsmark_get(struct Qdisc *sch, u32 classid)
{
- DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n",
- sch, PRIV(sch), classid);
+ pr_debug("dsmark_get(sch %p,[qdisc %p],classid %x)\n",
+ sch, qdisc_priv(sch), classid);
return TC_H_MIN(classid) + 1;
}
@@ -125,44 +99,56 @@ static void dsmark_put(struct Qdisc *sch, unsigned long cl)
{
}
+static const struct nla_policy dsmark_policy[TCA_DSMARK_MAX + 1] = {
+ [TCA_DSMARK_INDICES] = { .type = NLA_U16 },
+ [TCA_DSMARK_DEFAULT_INDEX] = { .type = NLA_U16 },
+ [TCA_DSMARK_SET_TC_INDEX] = { .type = NLA_FLAG },
+ [TCA_DSMARK_MASK] = { .type = NLA_U8 },
+ [TCA_DSMARK_VALUE] = { .type = NLA_U8 },
+};
+
static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
- struct rtattr **tca, unsigned long *arg)
+ struct nlattr **tca, unsigned long *arg)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
- struct rtattr *opt = tca[TCA_OPTIONS-1];
- struct rtattr *tb[TCA_DSMARK_MAX];
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
+ struct nlattr *opt = tca[TCA_OPTIONS];
+ struct nlattr *tb[TCA_DSMARK_MAX + 1];
int err = -EINVAL;
u8 mask = 0;
- DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x),"
+ pr_debug("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x),"
"arg 0x%lx\n", sch, p, classid, parent, *arg);
if (!dsmark_valid_index(p, *arg)) {
err = -ENOENT;
- goto rtattr_failure;
+ goto errout;
}
- if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt))
- goto rtattr_failure;
+ if (!opt)
+ goto errout;
- if (tb[TCA_DSMARK_MASK-1])
- mask = RTA_GET_U8(tb[TCA_DSMARK_MASK-1]);
+ err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy);
+ if (err < 0)
+ goto errout;
+
+ if (tb[TCA_DSMARK_MASK])
+ mask = nla_get_u8(tb[TCA_DSMARK_MASK]);
- if (tb[TCA_DSMARK_VALUE-1])
- p->value[*arg-1] = RTA_GET_U8(tb[TCA_DSMARK_VALUE-1]);
+ if (tb[TCA_DSMARK_VALUE])
+ p->value[*arg-1] = nla_get_u8(tb[TCA_DSMARK_VALUE]);
- if (tb[TCA_DSMARK_MASK-1])
+ if (tb[TCA_DSMARK_MASK])
p->mask[*arg-1] = mask;
err = 0;
-rtattr_failure:
+errout:
return err;
}
static int dsmark_delete(struct Qdisc *sch, unsigned long arg)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
if (!dsmark_valid_index(p, arg))
return -EINVAL;
@@ -173,12 +159,12 @@ static int dsmark_delete(struct Qdisc *sch, unsigned long arg)
return 0;
}
-static void dsmark_walk(struct Qdisc *sch,struct qdisc_walker *walker)
+static void dsmark_walk(struct Qdisc *sch, struct qdisc_walker *walker)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
int i;
- DPRINTK("dsmark_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
+ pr_debug("dsmark_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
if (walker->stop)
return;
@@ -197,34 +183,42 @@ ignore:
}
}
-static struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch,unsigned long cl)
+static inline struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch,
+ unsigned long cl)
{
- return &PRIV(sch)->filter_list;
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
+ return &p->filter_list;
}
/* --------------------------- Qdisc operations ---------------------------- */
-static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
+static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
int err;
- D2PRINTK("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+ pr_debug("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
if (p->set_tc_index) {
- /* FIXME: Safe with non-linear skbs? --RR */
switch (skb->protocol) {
- case __constant_htons(ETH_P_IP):
- skb->tc_index = ipv4_get_dsfield(ip_hdr(skb))
- & ~INET_ECN_MASK;
- break;
- case __constant_htons(ETH_P_IPV6):
- skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb))
- & ~INET_ECN_MASK;
- break;
- default:
- skb->tc_index = 0;
- break;
+ case __constant_htons(ETH_P_IP):
+ if (skb_cow_head(skb, sizeof(struct iphdr)))
+ goto drop;
+
+ skb->tc_index = ipv4_get_dsfield(ip_hdr(skb))
+ & ~INET_ECN_MASK;
+ break;
+
+ case __constant_htons(ETH_P_IPV6):
+ if (skb_cow_head(skb, sizeof(struct ipv6hdr)))
+ goto drop;
+
+ skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb))
+ & ~INET_ECN_MASK;
+ break;
+ default:
+ skb->tc_index = 0;
+ break;
}
}
@@ -234,7 +228,7 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
struct tcf_result res;
int result = tc_classify(skb, p->filter_list, &res);
- D2PRINTK("result %d class 0x%04x\n", result, res.classid);
+ pr_debug("result %d class 0x%04x\n", result, res.classid);
switch (result) {
#ifdef CONFIG_NET_CLS_ACT
@@ -242,14 +236,14 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
case TC_ACT_STOLEN:
kfree_skb(skb);
return NET_XMIT_SUCCESS;
+
case TC_ACT_SHOT:
- kfree_skb(skb);
- sch->qstats.drops++;
- return NET_XMIT_BYPASS;
+ goto drop;
#endif
case TC_ACT_OK:
skb->tc_index = TC_H_MIN(res.classid);
break;
+
default:
if (p->default_index != NO_DEFAULT_INDEX)
skb->tc_index = p->default_index;
@@ -257,7 +251,7 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
}
}
- err = p->q->enqueue(skb,p->q);
+ err = p->q->enqueue(skb, p->q);
if (err != NET_XMIT_SUCCESS) {
sch->qstats.drops++;
return err;
@@ -268,15 +262,20 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
sch->q.qlen++;
return NET_XMIT_SUCCESS;
+
+drop:
+ kfree_skb(skb);
+ sch->qstats.drops++;
+ return NET_XMIT_BYPASS;
}
static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
struct sk_buff *skb;
u32 index;
- D2PRINTK("dsmark_dequeue(sch %p,[qdisc %p])\n", sch, p);
+ pr_debug("dsmark_dequeue(sch %p,[qdisc %p])\n", sch, p);
skb = p->q->ops->dequeue(p->q);
if (skb == NULL)
@@ -285,39 +284,39 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
sch->q.qlen--;
index = skb->tc_index & (p->indices - 1);
- D2PRINTK("index %d->%d\n", skb->tc_index, index);
+ pr_debug("index %d->%d\n", skb->tc_index, index);
switch (skb->protocol) {
- case __constant_htons(ETH_P_IP):
- ipv4_change_dsfield(ip_hdr(skb), p->mask[index],
- p->value[index]);
- break;
- case __constant_htons(ETH_P_IPV6):
- ipv6_change_dsfield(ipv6_hdr(skb), p->mask[index],
- p->value[index]);
+ case __constant_htons(ETH_P_IP):
+ ipv4_change_dsfield(ip_hdr(skb), p->mask[index],
+ p->value[index]);
break;
- default:
- /*
- * Only complain if a change was actually attempted.
- * This way, we can send non-IP traffic through dsmark
- * and don't need yet another qdisc as a bypass.
- */
- if (p->mask[index] != 0xff || p->value[index])
- printk(KERN_WARNING "dsmark_dequeue: "
- "unsupported protocol %d\n",
- ntohs(skb->protocol));
+ case __constant_htons(ETH_P_IPV6):
+ ipv6_change_dsfield(ipv6_hdr(skb), p->mask[index],
+ p->value[index]);
break;
+ default:
+ /*
+ * Only complain if a change was actually attempted.
+ * This way, we can send non-IP traffic through dsmark
+ * and don't need yet another qdisc as a bypass.
+ */
+ if (p->mask[index] != 0xff || p->value[index])
+ printk(KERN_WARNING
+ "dsmark_dequeue: unsupported protocol %d\n",
+ ntohs(skb->protocol));
+ break;
}
return skb;
}
-static int dsmark_requeue(struct sk_buff *skb,struct Qdisc *sch)
+static int dsmark_requeue(struct sk_buff *skb, struct Qdisc *sch)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
int err;
- D2PRINTK("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+ pr_debug("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
err = p->q->ops->requeue(skb, p->q);
if (err != NET_XMIT_SUCCESS) {
@@ -333,10 +332,10 @@ static int dsmark_requeue(struct sk_buff *skb,struct Qdisc *sch)
static unsigned int dsmark_drop(struct Qdisc *sch)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
unsigned int len;
- DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
+ pr_debug("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
if (p->q->ops->drop == NULL)
return 0;
@@ -348,26 +347,32 @@ static unsigned int dsmark_drop(struct Qdisc *sch)
return len;
}
-static int dsmark_init(struct Qdisc *sch, struct rtattr *opt)
+static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
- struct rtattr *tb[TCA_DSMARK_MAX];
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
+ struct nlattr *tb[TCA_DSMARK_MAX + 1];
int err = -EINVAL;
u32 default_index = NO_DEFAULT_INDEX;
u16 indices;
u8 *mask;
- DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
+ pr_debug("dsmark_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
- if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt) < 0)
+ if (!opt)
goto errout;
- indices = RTA_GET_U16(tb[TCA_DSMARK_INDICES-1]);
- if (!indices || !dsmark_valid_indices(indices))
+ err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy);
+ if (err < 0)
+ goto errout;
+
+ err = -EINVAL;
+ indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
+
+ if (hweight32(indices) != 1)
goto errout;
- if (tb[TCA_DSMARK_DEFAULT_INDEX-1])
- default_index = RTA_GET_U16(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
+ if (tb[TCA_DSMARK_DEFAULT_INDEX])
+ default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
mask = kmalloc(indices * 2, GFP_KERNEL);
if (mask == NULL) {
@@ -383,34 +388,33 @@ static int dsmark_init(struct Qdisc *sch, struct rtattr *opt)
p->indices = indices;
p->default_index = default_index;
- p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]);
+ p->set_tc_index = nla_get_flag(tb[TCA_DSMARK_SET_TC_INDEX]);
p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, sch->handle);
if (p->q == NULL)
p->q = &noop_qdisc;
- DPRINTK("dsmark_init: qdisc %p\n", p->q);
+ pr_debug("dsmark_init: qdisc %p\n", p->q);
err = 0;
errout:
-rtattr_failure:
return err;
}
static void dsmark_reset(struct Qdisc *sch)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
- DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
+ pr_debug("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
qdisc_reset(p->q);
sch->q.qlen = 0;
}
static void dsmark_destroy(struct Qdisc *sch)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
- DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n", sch, p);
+ pr_debug("dsmark_destroy(sch %p,[qdisc %p])\n", sch, p);
tcf_destroy_chain(p->filter_list);
qdisc_destroy(p->q);
@@ -420,10 +424,10 @@ static void dsmark_destroy(struct Qdisc *sch)
static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
struct sk_buff *skb, struct tcmsg *tcm)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
- struct rtattr *opts = NULL;
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
+ struct nlattr *opts = NULL;
- DPRINTK("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n", sch, p, cl);
+ pr_debug("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n", sch, p, cl);
if (!dsmark_valid_index(p, cl))
return -EINVAL;
@@ -431,37 +435,41 @@ static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl-1);
tcm->tcm_info = p->q->handle;
- opts = RTA_NEST(skb, TCA_OPTIONS);
- RTA_PUT_U8(skb,TCA_DSMARK_MASK, p->mask[cl-1]);
- RTA_PUT_U8(skb,TCA_DSMARK_VALUE, p->value[cl-1]);
+ opts = nla_nest_start(skb, TCA_OPTIONS);
+ if (opts == NULL)
+ goto nla_put_failure;
+ NLA_PUT_U8(skb, TCA_DSMARK_MASK, p->mask[cl-1]);
+ NLA_PUT_U8(skb, TCA_DSMARK_VALUE, p->value[cl-1]);
- return RTA_NEST_END(skb, opts);
+ return nla_nest_end(skb, opts);
-rtattr_failure:
- return RTA_NEST_CANCEL(skb, opts);
+nla_put_failure:
+ return nla_nest_cancel(skb, opts);
}
static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
- struct rtattr *opts = NULL;
+ struct dsmark_qdisc_data *p = qdisc_priv(sch);
+ struct nlattr *opts = NULL;
- opts = RTA_NEST(skb, TCA_OPTIONS);
- RTA_PUT_U16(skb, TCA_DSMARK_INDICES, p->indices);
+ opts = nla_nest_start(skb, TCA_OPTIONS);
+ if (opts == NULL)
+ goto nla_put_failure;
+ NLA_PUT_U16(skb, TCA_DSMARK_INDICES, p->indices);
if (p->default_index != NO_DEFAULT_INDEX)
- RTA_PUT_U16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index);
+ NLA_PUT_U16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index);
if (p->set_tc_index)
- RTA_PUT_FLAG(skb, TCA_DSMARK_SET_TC_INDEX);
+ NLA_PUT_FLAG(skb, TCA_DSMARK_SET_TC_INDEX);
- return RTA_NEST_END(skb, opts);
+ return nla_nest_end(skb, opts);
-rtattr_failure:
- return RTA_NEST_CANCEL(skb, opts);
+nla_put_failure:
+ return nla_nest_cancel(skb, opts);
}
-static struct Qdisc_class_ops dsmark_class_ops = {
+static const struct Qdisc_class_ops dsmark_class_ops = {
.graft = dsmark_graft,
.leaf = dsmark_leaf,
.get = dsmark_get,
@@ -475,7 +483,7 @@ static struct Qdisc_class_ops dsmark_class_ops = {
.dump = dsmark_dump_class,
};
-static struct Qdisc_ops dsmark_qdisc_ops = {
+static struct Qdisc_ops dsmark_qdisc_ops __read_mostly = {
.next = NULL,
.cl_ops = &dsmark_class_ops,
.id = "dsmark",
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index c264308..95ed482 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -43,7 +43,7 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
return qdisc_reshape_fail(skb, sch);
}
-static int fifo_init(struct Qdisc *sch, struct rtattr *opt)
+static int fifo_init(struct Qdisc *sch, struct nlattr *opt)
{
struct fifo_sched_data *q = qdisc_priv(sch);
@@ -55,9 +55,9 @@ static int fifo_init(struct Qdisc *sch, struct rtattr *opt)
q->limit = limit;
} else {
- struct tc_fifo_qopt *ctl = RTA_DATA(opt);
+ struct tc_fifo_qopt *ctl = nla_data(opt);
- if (RTA_PAYLOAD(opt) < sizeof(*ctl))
+ if (nla_len(opt) < sizeof(*ctl))
return -EINVAL;
q->limit = ctl->limit;
@@ -71,14 +71,14 @@ static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
struct fifo_sched_data *q = qdisc_priv(sch);
struct tc_fifo_qopt opt = { .limit = q->limit };
- RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
return skb->len;
-rtattr_failure:
+nla_put_failure:
return -1;
}
-struct Qdisc_ops pfifo_qdisc_ops = {
+struct Qdisc_ops pfifo_qdisc_ops __read_mostly = {
.id = "pfifo",
.priv_size = sizeof(struct fifo_sched_data),
.enqueue = pfifo_enqueue,
@@ -91,8 +91,9 @@ struct Qdisc_ops pfifo_qdisc_ops = {
.dump = fifo_dump,
.owner = THIS_MODULE,
};
+EXPORT_SYMBOL(pfifo_qdisc_ops);
-struct Qdisc_ops bfifo_qdisc_ops = {
+struct Qdisc_ops bfifo_qdisc_ops __read_mostly = {
.id = "bfifo",
.priv_size = sizeof(struct fifo_sched_data),
.enqueue = bfifo_enqueue,
@@ -105,6 +106,4 @@ struct Qdisc_ops bfifo_qdisc_ops = {
.dump = fifo_dump,
.owner = THIS_MODULE,
};
-
EXPORT_SYMBOL(bfifo_qdisc_ops);
-EXPORT_SYMBOL(pfifo_qdisc_ops);
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index e595e65..10b5c08 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -40,16 +40,22 @@
*/
void qdisc_lock_tree(struct net_device *dev)
+ __acquires(dev->queue_lock)
+ __acquires(dev->ingress_lock)
{
spin_lock_bh(&dev->queue_lock);
spin_lock(&dev->ingress_lock);
}
+EXPORT_SYMBOL(qdisc_lock_tree);
void qdisc_unlock_tree(struct net_device *dev)
+ __releases(dev->ingress_lock)
+ __releases(dev->queue_lock)
{
spin_unlock(&dev->ingress_lock);
spin_unlock_bh(&dev->queue_lock);
}
+EXPORT_SYMBOL(qdisc_unlock_tree);
static inline int qdisc_qlen(struct Qdisc *q)
{
@@ -211,13 +217,6 @@ static void dev_watchdog(unsigned long arg)
dev_put(dev);
}
-static void dev_watchdog_init(struct net_device *dev)
-{
- init_timer(&dev->watchdog_timer);
- dev->watchdog_timer.data = (unsigned long)dev;
- dev->watchdog_timer.function = dev_watchdog;
-}
-
void __netdev_watchdog_up(struct net_device *dev)
{
if (dev->tx_timeout) {
@@ -256,6 +255,7 @@ void netif_carrier_on(struct net_device *dev)
__netdev_watchdog_up(dev);
}
}
+EXPORT_SYMBOL(netif_carrier_on);
/**
* netif_carrier_off - clear carrier
@@ -268,6 +268,7 @@ void netif_carrier_off(struct net_device *dev)
if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state))
linkwatch_fire_event(dev);
}
+EXPORT_SYMBOL(netif_carrier_off);
/* "NOOP" scheduler: the best scheduler, recommended for all interfaces
under all circumstances. It is difficult to invent anything faster or
@@ -294,7 +295,7 @@ static int noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
return NET_XMIT_CN;
}
-struct Qdisc_ops noop_qdisc_ops = {
+struct Qdisc_ops noop_qdisc_ops __read_mostly = {
.id = "noop",
.priv_size = 0,
.enqueue = noop_enqueue,
@@ -310,8 +311,9 @@ struct Qdisc noop_qdisc = {
.ops = &noop_qdisc_ops,
.list = LIST_HEAD_INIT(noop_qdisc.list),
};
+EXPORT_SYMBOL(noop_qdisc);
-static struct Qdisc_ops noqueue_qdisc_ops = {
+static struct Qdisc_ops noqueue_qdisc_ops __read_mostly = {
.id = "noqueue",
.priv_size = 0,
.enqueue = noop_enqueue,
@@ -395,14 +397,14 @@ static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS };
memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1);
- RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
return skb->len;
-rtattr_failure:
+nla_put_failure:
return -1;
}
-static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt)
+static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
{
int prio;
struct sk_buff_head *list = qdisc_priv(qdisc);
@@ -413,7 +415,7 @@ static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt)
return 0;
}
-static struct Qdisc_ops pfifo_fast_ops = {
+static struct Qdisc_ops pfifo_fast_ops __read_mostly = {
.id = "pfifo_fast",
.priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
.enqueue = pfifo_fast_enqueue,
@@ -474,16 +476,18 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops,
errout:
return NULL;
}
+EXPORT_SYMBOL(qdisc_create_dflt);
/* Under dev->queue_lock and BH! */
void qdisc_reset(struct Qdisc *qdisc)
{
- struct Qdisc_ops *ops = qdisc->ops;
+ const struct Qdisc_ops *ops = qdisc->ops;
if (ops->reset)
ops->reset(qdisc);
}
+EXPORT_SYMBOL(qdisc_reset);
/* this is the rcu callback function to clean up a qdisc when there
* are no further references to it */
@@ -498,7 +502,7 @@ static void __qdisc_destroy(struct rcu_head *head)
void qdisc_destroy(struct Qdisc *qdisc)
{
- struct Qdisc_ops *ops = qdisc->ops;
+ const struct Qdisc_ops *ops = qdisc->ops;
if (qdisc->flags & TCQ_F_BUILTIN ||
!atomic_dec_and_test(&qdisc->refcnt))
@@ -515,6 +519,7 @@ void qdisc_destroy(struct Qdisc *qdisc)
dev_put(qdisc->dev);
call_rcu(&qdisc->q_rcu, __qdisc_destroy);
}
+EXPORT_SYMBOL(qdisc_destroy);
void dev_activate(struct net_device *dev)
{
@@ -608,7 +613,7 @@ void dev_init_scheduler(struct net_device *dev)
INIT_LIST_HEAD(&dev->qdisc_list);
qdisc_unlock_tree(dev);
- dev_watchdog_init(dev);
+ setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev);
}
void dev_shutdown(struct net_device *dev)
@@ -629,12 +634,3 @@ void dev_shutdown(struct net_device *dev)
BUG_TRAP(!timer_pending(&dev->watchdog_timer));
qdisc_unlock_tree(dev);
}
-
-EXPORT_SYMBOL(netif_carrier_on);
-EXPORT_SYMBOL(netif_carrier_off);
-EXPORT_SYMBOL(noop_qdisc);
-EXPORT_SYMBOL(qdisc_create_dflt);
-EXPORT_SYMBOL(qdisc_destroy);
-EXPORT_SYMBOL(qdisc_reset);
-EXPORT_SYMBOL(qdisc_lock_tree);
-EXPORT_SYMBOL(qdisc_unlock_tree);
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 3cc6dda..3a9d226 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -350,16 +350,16 @@ static inline void gred_destroy_vq(struct gred_sched_data *q)
kfree(q);
}
-static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps)
+static inline int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps)
{
struct gred_sched *table = qdisc_priv(sch);
struct tc_gred_sopt *sopt;
int i;
- if (dps == NULL || RTA_PAYLOAD(dps) < sizeof(*sopt))
+ if (dps == NULL)
return -EINVAL;
- sopt = RTA_DATA(dps);
+ sopt = nla_data(dps);
if (sopt->DPs > MAX_DPs || sopt->DPs == 0 || sopt->def_DP >= sopt->DPs)
return -EINVAL;
@@ -425,28 +425,37 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp,
return 0;
}
-static int gred_change(struct Qdisc *sch, struct rtattr *opt)
+static const struct nla_policy gred_policy[TCA_GRED_MAX + 1] = {
+ [TCA_GRED_PARMS] = { .len = sizeof(struct tc_gred_qopt) },
+ [TCA_GRED_STAB] = { .len = 256 },
+ [TCA_GRED_DPS] = { .len = sizeof(struct tc_gred_sopt) },
+};
+
+static int gred_change(struct Qdisc *sch, struct nlattr *opt)
{
struct gred_sched *table = qdisc_priv(sch);
struct tc_gred_qopt *ctl;
- struct rtattr *tb[TCA_GRED_MAX];
- int err = -EINVAL, prio = GRED_DEF_PRIO;
+ struct nlattr *tb[TCA_GRED_MAX + 1];
+ int err, prio = GRED_DEF_PRIO;
u8 *stab;
- if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_MAX, opt))
+ if (opt == NULL)
return -EINVAL;
- if (tb[TCA_GRED_PARMS-1] == NULL && tb[TCA_GRED_STAB-1] == NULL)
+ err = nla_parse_nested(tb, TCA_GRED_MAX, opt, gred_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_GRED_PARMS] == NULL && tb[TCA_GRED_STAB] == NULL)
return gred_change_table_def(sch, opt);
- if (tb[TCA_GRED_PARMS-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) ||
- tb[TCA_GRED_STAB-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_GRED_STAB-1]) < 256)
+ if (tb[TCA_GRED_PARMS] == NULL ||
+ tb[TCA_GRED_STAB] == NULL)
return -EINVAL;
- ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]);
- stab = RTA_DATA(tb[TCA_GRED_STAB-1]);
+ err = -EINVAL;
+ ctl = nla_data(tb[TCA_GRED_PARMS]);
+ stab = nla_data(tb[TCA_GRED_STAB]);
if (ctl->DP >= table->DPs)
goto errout;
@@ -486,23 +495,28 @@ errout:
return err;
}
-static int gred_init(struct Qdisc *sch, struct rtattr *opt)
+static int gred_init(struct Qdisc *sch, struct nlattr *opt)
{
- struct rtattr *tb[TCA_GRED_MAX];
+ struct nlattr *tb[TCA_GRED_MAX + 1];
+ int err;
- if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_MAX, opt))
+ if (opt == NULL)
return -EINVAL;
- if (tb[TCA_GRED_PARMS-1] || tb[TCA_GRED_STAB-1])
+ err = nla_parse_nested(tb, TCA_GRED_MAX, opt, gred_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_GRED_PARMS] || tb[TCA_GRED_STAB])
return -EINVAL;
- return gred_change_table_def(sch, tb[TCA_GRED_DPS-1]);
+ return gred_change_table_def(sch, tb[TCA_GRED_DPS]);
}
static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct gred_sched *table = qdisc_priv(sch);
- struct rtattr *parms, *opts = NULL;
+ struct nlattr *parms, *opts = NULL;
int i;
struct tc_gred_sopt sopt = {
.DPs = table->DPs,
@@ -511,9 +525,13 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
.flags = table->red_flags,
};
- opts = RTA_NEST(skb, TCA_OPTIONS);
- RTA_PUT(skb, TCA_GRED_DPS, sizeof(sopt), &sopt);
- parms = RTA_NEST(skb, TCA_GRED_PARMS);
+ opts = nla_nest_start(skb, TCA_OPTIONS);
+ if (opts == NULL)
+ goto nla_put_failure;
+ NLA_PUT(skb, TCA_GRED_DPS, sizeof(sopt), &sopt);
+ parms = nla_nest_start(skb, TCA_GRED_PARMS);
+ if (parms == NULL)
+ goto nla_put_failure;
for (i = 0; i < MAX_DPs; i++) {
struct gred_sched_data *q = table->tab[i];
@@ -555,15 +573,16 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
opt.qave = red_calc_qavg(&q->parms, q->parms.qavg);
append_opt:
- RTA_APPEND(skb, sizeof(opt), &opt);
+ if (nla_append(skb, sizeof(opt), &opt) < 0)
+ goto nla_put_failure;
}
- RTA_NEST_END(skb, parms);
+ nla_nest_end(skb, parms);
- return RTA_NEST_END(skb, opts);
+ return nla_nest_end(skb, opts);
-rtattr_failure:
- return RTA_NEST_CANCEL(skb, opts);
+nla_put_failure:
+ return nla_nest_cancel(skb, opts);
}
static void gred_destroy(struct Qdisc *sch)
@@ -577,7 +596,7 @@ static void gred_destroy(struct Qdisc *sch)
}
}
-static struct Qdisc_ops gred_qdisc_ops = {
+static struct Qdisc_ops gred_qdisc_ops __read_mostly = {
.id = "gred",
.priv_size = sizeof(struct gred_sched),
.enqueue = gred_enqueue,
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index a6ad491..87293d0 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -986,41 +986,46 @@ hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
cl->cl_flags |= HFSC_USC;
}
+static const struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = {
+ [TCA_HFSC_RSC] = { .len = sizeof(struct tc_service_curve) },
+ [TCA_HFSC_FSC] = { .len = sizeof(struct tc_service_curve) },
+ [TCA_HFSC_USC] = { .len = sizeof(struct tc_service_curve) },
+};
+
static int
hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
- struct rtattr **tca, unsigned long *arg)
+ struct nlattr **tca, unsigned long *arg)
{
struct hfsc_sched *q = qdisc_priv(sch);
struct hfsc_class *cl = (struct hfsc_class *)*arg;
struct hfsc_class *parent = NULL;
- struct rtattr *opt = tca[TCA_OPTIONS-1];
- struct rtattr *tb[TCA_HFSC_MAX];
+ struct nlattr *opt = tca[TCA_OPTIONS];
+ struct nlattr *tb[TCA_HFSC_MAX + 1];
struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
u64 cur_time;
+ int err;
- if (opt == NULL || rtattr_parse_nested(tb, TCA_HFSC_MAX, opt))
+ if (opt == NULL)
return -EINVAL;
- if (tb[TCA_HFSC_RSC-1]) {
- if (RTA_PAYLOAD(tb[TCA_HFSC_RSC-1]) < sizeof(*rsc))
- return -EINVAL;
- rsc = RTA_DATA(tb[TCA_HFSC_RSC-1]);
+ err = nla_parse_nested(tb, TCA_HFSC_MAX, opt, hfsc_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_HFSC_RSC]) {
+ rsc = nla_data(tb[TCA_HFSC_RSC]);
if (rsc->m1 == 0 && rsc->m2 == 0)
rsc = NULL;
}
- if (tb[TCA_HFSC_FSC-1]) {
- if (RTA_PAYLOAD(tb[TCA_HFSC_FSC-1]) < sizeof(*fsc))
- return -EINVAL;
- fsc = RTA_DATA(tb[TCA_HFSC_FSC-1]);
+ if (tb[TCA_HFSC_FSC]) {
+ fsc = nla_data(tb[TCA_HFSC_FSC]);
if (fsc->m1 == 0 && fsc->m2 == 0)
fsc = NULL;
}
- if (tb[TCA_HFSC_USC-1]) {
- if (RTA_PAYLOAD(tb[TCA_HFSC_USC-1]) < sizeof(*usc))
- return -EINVAL;
- usc = RTA_DATA(tb[TCA_HFSC_USC-1]);
+ if (tb[TCA_HFSC_USC]) {
+ usc = nla_data(tb[TCA_HFSC_USC]);
if (usc->m1 == 0 && usc->m2 == 0)
usc = NULL;
}
@@ -1050,10 +1055,10 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
}
sch_tree_unlock(sch);
- if (tca[TCA_RATE-1])
+ if (tca[TCA_RATE])
gen_replace_estimator(&cl->bstats, &cl->rate_est,
&sch->dev->queue_lock,
- tca[TCA_RATE-1]);
+ tca[TCA_RATE]);
return 0;
}
@@ -1106,9 +1111,9 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
cl->cl_pcvtoff = parent->cl_cvtoff;
sch_tree_unlock(sch);
- if (tca[TCA_RATE-1])
+ if (tca[TCA_RATE])
gen_new_estimator(&cl->bstats, &cl->rate_est,
- &sch->dev->queue_lock, tca[TCA_RATE-1]);
+ &sch->dev->queue_lock, tca[TCA_RATE]);
*arg = (unsigned long)cl;
return 0;
}
@@ -1304,11 +1309,11 @@ hfsc_dump_sc(struct sk_buff *skb, int attr, struct internal_sc *sc)
tsc.m1 = sm2m(sc->sm1);
tsc.d = dx2d(sc->dx);
tsc.m2 = sm2m(sc->sm2);
- RTA_PUT(skb, attr, sizeof(tsc), &tsc);
+ NLA_PUT(skb, attr, sizeof(tsc), &tsc);
return skb->len;
- rtattr_failure:
+ nla_put_failure:
return -1;
}
@@ -1317,19 +1322,19 @@ hfsc_dump_curves(struct sk_buff *skb, struct hfsc_class *cl)
{
if ((cl->cl_flags & HFSC_RSC) &&
(hfsc_dump_sc(skb, TCA_HFSC_RSC, &cl->cl_rsc) < 0))
- goto rtattr_failure;
+ goto nla_put_failure;
if ((cl->cl_flags & HFSC_FSC) &&
(hfsc_dump_sc(skb, TCA_HFSC_FSC, &cl->cl_fsc) < 0))
- goto rtattr_failure;
+ goto nla_put_failure;
if ((cl->cl_flags & HFSC_USC) &&
(hfsc_dump_sc(skb, TCA_HFSC_USC, &cl->cl_usc) < 0))
- goto rtattr_failure;
+ goto nla_put_failure;
return skb->len;
- rtattr_failure:
+ nla_put_failure:
return -1;
}
@@ -1338,22 +1343,23 @@ hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb,
struct tcmsg *tcm)
{
struct hfsc_class *cl = (struct hfsc_class *)arg;
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta = (struct rtattr *)b;
+ struct nlattr *nest;
tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT;
tcm->tcm_handle = cl->classid;
if (cl->level == 0)
tcm->tcm_info = cl->qdisc->handle;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
if (hfsc_dump_curves(skb, cl) < 0)
- goto rtattr_failure;
- rta->rta_len = skb_tail_pointer(skb) - b;
+ goto nla_put_failure;
+ nla_nest_end(skb, nest);
return skb->len;
- rtattr_failure:
- nlmsg_trim(skb, b);
+ nla_put_failure:
+ nla_nest_cancel(skb, nest);
return -1;
}
@@ -1423,15 +1429,15 @@ hfsc_schedule_watchdog(struct Qdisc *sch)
}
static int
-hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
+hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
{
struct hfsc_sched *q = qdisc_priv(sch);
struct tc_hfsc_qopt *qopt;
unsigned int i;
- if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
+ if (opt == NULL || nla_len(opt) < sizeof(*qopt))
return -EINVAL;
- qopt = RTA_DATA(opt);
+ qopt = nla_data(opt);
q->defcls = qopt->defcls;
for (i = 0; i < HFSC_HSIZE; i++)
@@ -1459,14 +1465,14 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
}
static int
-hfsc_change_qdisc(struct Qdisc *sch, struct rtattr *opt)
+hfsc_change_qdisc(struct Qdisc *sch, struct nlattr *opt)
{
struct hfsc_sched *q = qdisc_priv(sch);
struct tc_hfsc_qopt *qopt;
- if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
+ if (opt == NULL || nla_len(opt) < sizeof(*qopt))
return -EINVAL;
- qopt = RTA_DATA(opt);
+ qopt = nla_data(opt);
sch_tree_lock(sch);
q->defcls = qopt->defcls;
@@ -1550,10 +1556,10 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
struct tc_hfsc_qopt qopt;
qopt.defcls = q->defcls;
- RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
+ NLA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
return skb->len;
- rtattr_failure:
+ nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -1698,7 +1704,7 @@ hfsc_drop(struct Qdisc *sch)
return 0;
}
-static struct Qdisc_class_ops hfsc_class_ops = {
+static const struct Qdisc_class_ops hfsc_class_ops = {
.change = hfsc_change_class,
.delete = hfsc_delete_class,
.graft = hfsc_graft_class,
@@ -1714,7 +1720,7 @@ static struct Qdisc_class_ops hfsc_class_ops = {
.walk = hfsc_walk
};
-static struct Qdisc_ops hfsc_qdisc_ops = {
+static struct Qdisc_ops hfsc_qdisc_ops __read_mostly = {
.id = "hfsc",
.init = hfsc_init_qdisc,
.change = hfsc_change_qdisc,
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 5e608a6..e1a579e 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -214,10 +214,6 @@ static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
* then finish and return direct queue.
*/
#define HTB_DIRECT (struct htb_class*)-1
-static inline u32 htb_classid(struct htb_class *cl)
-{
- return (cl && cl != HTB_DIRECT) ? cl->classid : TC_H_UNSPEC;
-}
static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
int *qerr)
@@ -996,19 +992,33 @@ static void htb_reset(struct Qdisc *sch)
INIT_LIST_HEAD(q->drops + i);
}
-static int htb_init(struct Qdisc *sch, struct rtattr *opt)
+static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
+ [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) },
+ [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) },
+ [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+ [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+};
+
+static int htb_init(struct Qdisc *sch, struct nlattr *opt)
{
struct htb_sched *q = qdisc_priv(sch);
- struct rtattr *tb[TCA_HTB_INIT];
+ struct nlattr *tb[TCA_HTB_INIT + 1];
struct tc_htb_glob *gopt;
+ int err;
int i;
- if (!opt || rtattr_parse_nested(tb, TCA_HTB_INIT, opt) ||
- tb[TCA_HTB_INIT - 1] == NULL ||
- RTA_PAYLOAD(tb[TCA_HTB_INIT - 1]) < sizeof(*gopt)) {
+
+ if (!opt)
+ return -EINVAL;
+
+ err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_HTB_INIT] == NULL) {
printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
return -EINVAL;
}
- gopt = RTA_DATA(tb[TCA_HTB_INIT - 1]);
+ gopt = nla_data(tb[TCA_HTB_INIT]);
if (gopt->version != HTB_VER >> 16) {
printk(KERN_ERR
"HTB: need tc/htb version %d (minor is %d), you have %d\n",
@@ -1039,25 +1049,29 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt)
static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct htb_sched *q = qdisc_priv(sch);
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
struct tc_htb_glob gopt;
+
spin_lock_bh(&sch->dev->queue_lock);
- gopt.direct_pkts = q->direct_pkts;
+ gopt.direct_pkts = q->direct_pkts;
gopt.version = HTB_VER;
gopt.rate2quantum = q->rate2quantum;
gopt.defcls = q->defcls;
gopt.debug = 0;
- rta = (struct rtattr *)b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
- RTA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
- rta->rta_len = skb_tail_pointer(skb) - b;
+
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
+ NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
+ nla_nest_end(skb, nest);
+
spin_unlock_bh(&sch->dev->queue_lock);
return skb->len;
-rtattr_failure:
+
+nla_put_failure:
spin_unlock_bh(&sch->dev->queue_lock);
- nlmsg_trim(skb, skb_tail_pointer(skb));
+ nla_nest_cancel(skb, nest);
return -1;
}
@@ -1065,8 +1079,7 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
struct sk_buff *skb, struct tcmsg *tcm)
{
struct htb_class *cl = (struct htb_class *)arg;
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
struct tc_htb_opt opt;
spin_lock_bh(&sch->dev->queue_lock);
@@ -1075,8 +1088,9 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
if (!cl->level && cl->un.leaf.q)
tcm->tcm_info = cl->un.leaf.q->handle;
- rta = (struct rtattr *)b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
memset(&opt, 0, sizeof(opt));
@@ -1087,13 +1101,15 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
opt.quantum = cl->un.leaf.quantum;
opt.prio = cl->un.leaf.prio;
opt.level = cl->level;
- RTA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
- rta->rta_len = skb_tail_pointer(skb) - b;
+ NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
+
+ nla_nest_end(skb, nest);
spin_unlock_bh(&sch->dev->queue_lock);
return skb->len;
-rtattr_failure:
+
+nla_put_failure:
spin_unlock_bh(&sch->dev->queue_lock);
- nlmsg_trim(skb, b);
+ nla_nest_cancel(skb, nest);
return -1;
}
@@ -1294,29 +1310,35 @@ static void htb_put(struct Qdisc *sch, unsigned long arg)
}
static int htb_change_class(struct Qdisc *sch, u32 classid,
- u32 parentid, struct rtattr **tca,
+ u32 parentid, struct nlattr **tca,
unsigned long *arg)
{
int err = -EINVAL;
struct htb_sched *q = qdisc_priv(sch);
struct htb_class *cl = (struct htb_class *)*arg, *parent;
- struct rtattr *opt = tca[TCA_OPTIONS - 1];
+ struct nlattr *opt = tca[TCA_OPTIONS];
struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
- struct rtattr *tb[TCA_HTB_RTAB];
+ struct nlattr *tb[TCA_HTB_RTAB + 1];
struct tc_htb_opt *hopt;
/* extract all subattrs from opt attr */
- if (!opt || rtattr_parse_nested(tb, TCA_HTB_RTAB, opt) ||
- tb[TCA_HTB_PARMS - 1] == NULL ||
- RTA_PAYLOAD(tb[TCA_HTB_PARMS - 1]) < sizeof(*hopt))
+ if (!opt)
+ goto failure;
+
+ err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
+ if (err < 0)
+ goto failure;
+
+ err = -EINVAL;
+ if (tb[TCA_HTB_PARMS] == NULL)
goto failure;
parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
- hopt = RTA_DATA(tb[TCA_HTB_PARMS - 1]);
+ hopt = nla_data(tb[TCA_HTB_PARMS]);
- rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB - 1]);
- ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB - 1]);
+ rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
+ ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
if (!rtab || !ctab)
goto failure;
@@ -1324,12 +1346,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
struct Qdisc *new_q;
int prio;
struct {
- struct rtattr rta;
+ struct nlattr nla;
struct gnet_estimator opt;
} est = {
- .rta = {
- .rta_len = RTA_LENGTH(sizeof(est.opt)),
- .rta_type = TCA_RATE,
+ .nla = {
+ .nla_len = nla_attr_size(sizeof(est.opt)),
+ .nla_type = TCA_RATE,
},
.opt = {
/* 4s interval, 16s averaging constant */
@@ -1354,7 +1376,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
gen_new_estimator(&cl->bstats, &cl->rate_est,
&sch->dev->queue_lock,
- tca[TCA_RATE-1] ? : &est.rta);
+ tca[TCA_RATE] ? : &est.nla);
cl->refcnt = 1;
INIT_LIST_HEAD(&cl->sibling);
INIT_HLIST_NODE(&cl->hlist);
@@ -1407,10 +1429,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
list_add_tail(&cl->sibling,
parent ? &parent->children : &q->root);
} else {
- if (tca[TCA_RATE-1])
+ if (tca[TCA_RATE])
gen_replace_estimator(&cl->bstats, &cl->rate_est,
&sch->dev->queue_lock,
- tca[TCA_RATE-1]);
+ tca[TCA_RATE]);
sch_tree_lock(sch);
}
@@ -1529,7 +1551,7 @@ static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
}
}
-static struct Qdisc_class_ops htb_class_ops = {
+static const struct Qdisc_class_ops htb_class_ops = {
.graft = htb_graft,
.leaf = htb_leaf,
.qlen_notify = htb_qlen_notify,
@@ -1545,7 +1567,7 @@ static struct Qdisc_class_ops htb_class_ops = {
.dump_stats = htb_dump_class_stats,
};
-static struct Qdisc_ops htb_qdisc_ops = {
+static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
.next = NULL,
.cl_ops = &htb_class_ops,
.id = "htb",
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 3f8335e..3f72d52 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -19,127 +19,71 @@
#include <net/pkt_sched.h>
-#undef DEBUG_INGRESS
-
-#ifdef DEBUG_INGRESS /* control */
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define DPRINTK(format,args...)
-#endif
-
-#if 0 /* data */
-#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define D2PRINTK(format,args...)
-#endif
-
-
-#define PRIV(sch) qdisc_priv(sch)
-
-
-/* Thanks to Doron Oz for this hack
-*/
-#ifndef CONFIG_NET_CLS_ACT
-#ifdef CONFIG_NETFILTER
+/* Thanks to Doron Oz for this hack */
+#if !defined(CONFIG_NET_CLS_ACT) && defined(CONFIG_NETFILTER)
static int nf_registered;
#endif
-#endif
struct ingress_qdisc_data {
- struct Qdisc *q;
struct tcf_proto *filter_list;
};
-
/* ------------------------- Class/flow operations ------------------------- */
-
-static int ingress_graft(struct Qdisc *sch,unsigned long arg,
- struct Qdisc *new,struct Qdisc **old)
+static int ingress_graft(struct Qdisc *sch, unsigned long arg,
+ struct Qdisc *new, struct Qdisc **old)
{
-#ifdef DEBUG_INGRESS
- struct ingress_qdisc_data *p = PRIV(sch);
-#endif
-
- DPRINTK("ingress_graft(sch %p,[qdisc %p],new %p,old %p)\n",
- sch, p, new, old);
- DPRINTK("\n ingress_graft: You cannot add qdiscs to classes");
- return 1;
+ return -EOPNOTSUPP;
}
-
static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
{
return NULL;
}
-
-static unsigned long ingress_get(struct Qdisc *sch,u32 classid)
+static unsigned long ingress_get(struct Qdisc *sch, u32 classid)
{
-#ifdef DEBUG_INGRESS
- struct ingress_qdisc_data *p = PRIV(sch);
-#endif
- DPRINTK("ingress_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
return TC_H_MIN(classid) + 1;
}
-
static unsigned long ingress_bind_filter(struct Qdisc *sch,
- unsigned long parent, u32 classid)
+ unsigned long parent, u32 classid)
{
return ingress_get(sch, classid);
}
-
static void ingress_put(struct Qdisc *sch, unsigned long cl)
{
}
-
static int ingress_change(struct Qdisc *sch, u32 classid, u32 parent,
- struct rtattr **tca, unsigned long *arg)
+ struct nlattr **tca, unsigned long *arg)
{
-#ifdef DEBUG_INGRESS
- struct ingress_qdisc_data *p = PRIV(sch);
-#endif
- DPRINTK("ingress_change(sch %p,[qdisc %p],classid %x,parent %x),"
- "arg 0x%lx\n", sch, p, classid, parent, *arg);
- DPRINTK("No effect. sch_ingress doesn't maintain classes at the moment");
return 0;
}
-
-
-static void ingress_walk(struct Qdisc *sch,struct qdisc_walker *walker)
+static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker)
{
-#ifdef DEBUG_INGRESS
- struct ingress_qdisc_data *p = PRIV(sch);
-#endif
- DPRINTK("ingress_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
- DPRINTK("No effect. sch_ingress doesn't maintain classes at the moment");
+ return;
}
-
-static struct tcf_proto **ingress_find_tcf(struct Qdisc *sch,unsigned long cl)
+static struct tcf_proto **ingress_find_tcf(struct Qdisc *sch, unsigned long cl)
{
- struct ingress_qdisc_data *p = PRIV(sch);
+ struct ingress_qdisc_data *p = qdisc_priv(sch);
return &p->filter_list;
}
-
/* --------------------------- Qdisc operations ---------------------------- */
-
-static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
+static int ingress_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
- struct ingress_qdisc_data *p = PRIV(sch);
+ struct ingress_qdisc_data *p = qdisc_priv(sch);
struct tcf_result res;
int result;
- D2PRINTK("ingress_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
result = tc_classify(skb, p->filter_list, &res);
- D2PRINTK("result %d class 0x%04x\n", result, res.classid);
+
/*
* Unlike normal "enqueue" functions, ingress_enqueue returns a
* firewall FW_* code.
@@ -148,23 +92,22 @@ static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
sch->bstats.packets++;
sch->bstats.bytes += skb->len;
switch (result) {
- case TC_ACT_SHOT:
- result = TC_ACT_SHOT;
- sch->qstats.drops++;
- break;
- case TC_ACT_STOLEN:
- case TC_ACT_QUEUED:
- result = TC_ACT_STOLEN;
- break;
- case TC_ACT_RECLASSIFY:
- case TC_ACT_OK:
- skb->tc_index = TC_H_MIN(res.classid);
- default:
- result = TC_ACT_OK;
- break;
+ case TC_ACT_SHOT:
+ result = TC_ACT_SHOT;
+ sch->qstats.drops++;
+ break;
+ case TC_ACT_STOLEN:
+ case TC_ACT_QUEUED:
+ result = TC_ACT_STOLEN;
+ break;
+ case TC_ACT_RECLASSIFY:
+ case TC_ACT_OK:
+ skb->tc_index = TC_H_MIN(res.classid);
+ default:
+ result = TC_ACT_OK;
+ break;
}
#else
- D2PRINTK("Overriding result to ACCEPT\n");
result = NF_ACCEPT;
sch->bstats.packets++;
sch->bstats.bytes += skb->len;
@@ -173,39 +116,8 @@ static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
return result;
}
-
-static struct sk_buff *ingress_dequeue(struct Qdisc *sch)
-{
-/*
- struct ingress_qdisc_data *p = PRIV(sch);
- D2PRINTK("ingress_dequeue(sch %p,[qdisc %p])\n",sch,PRIV(p));
-*/
- return NULL;
-}
-
-
-static int ingress_requeue(struct sk_buff *skb,struct Qdisc *sch)
-{
-/*
- struct ingress_qdisc_data *p = PRIV(sch);
- D2PRINTK("ingress_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,PRIV(p));
-*/
- return 0;
-}
-
-static unsigned int ingress_drop(struct Qdisc *sch)
-{
-#ifdef DEBUG_INGRESS
- struct ingress_qdisc_data *p = PRIV(sch);
-#endif
- DPRINTK("ingress_drop(sch %p,[qdisc %p])\n", sch, p);
- return 0;
-}
-
-#ifndef CONFIG_NET_CLS_ACT
-#ifdef CONFIG_NETFILTER
-static unsigned int
-ing_hook(unsigned int hook, struct sk_buff *skb,
+#if !defined(CONFIG_NET_CLS_ACT) && defined(CONFIG_NETFILTER)
+static unsigned int ing_hook(unsigned int hook, struct sk_buff *skb,
const struct net_device *indev,
const struct net_device *outdev,
int (*okfn)(struct sk_buff *))
@@ -213,12 +125,7 @@ ing_hook(unsigned int hook, struct sk_buff *skb,
struct Qdisc *q;
struct net_device *dev = skb->dev;
- int fwres=NF_ACCEPT;
-
- DPRINTK("ing_hook: skb %s dev=%s len=%u\n",
- skb->sk ? "(owned)" : "(unowned)",
- skb->dev ? skb->dev->name : "(no dev)",
- skb->len);
+ int fwres = NF_ACCEPT;
if (dev->qdisc_ingress) {
spin_lock(&dev->ingress_lock);
@@ -231,168 +138,101 @@ ing_hook(unsigned int hook, struct sk_buff *skb,
}
/* after ipt_filter */
-static struct nf_hook_ops ing_ops = {
- .hook = ing_hook,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_FILTER + 1,
-};
-
-static struct nf_hook_ops ing6_ops = {
- .hook = ing_hook,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_PRE_ROUTING,
- .priority = NF_IP6_PRI_FILTER + 1,
+static struct nf_hook_ops ing_ops[] __read_mostly = {
+ {
+ .hook = ing_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP_PRI_FILTER + 1,
+ },
+ {
+ .hook = ing_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP6_PRI_FILTER + 1,
+ },
};
-
-#endif
#endif
-static int ingress_init(struct Qdisc *sch,struct rtattr *opt)
+static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
{
- struct ingress_qdisc_data *p = PRIV(sch);
-
-/* Make sure either netfilter or preferably CLS_ACT is
-* compiled in */
-#ifndef CONFIG_NET_CLS_ACT
-#ifndef CONFIG_NETFILTER
- printk("You MUST compile classifier actions into the kernel\n");
- return -EINVAL;
-#else
+#if !defined(CONFIG_NET_CLS_ACT) && defined(CONFIG_NETFILTER)
printk("Ingress scheduler: Classifier actions prefered over netfilter\n");
-#endif
-#endif
-#ifndef CONFIG_NET_CLS_ACT
-#ifdef CONFIG_NETFILTER
if (!nf_registered) {
- if (nf_register_hook(&ing_ops) < 0) {
+ if (nf_register_hooks(ing_ops, ARRAY_SIZE(ing_ops)) < 0) {
printk("ingress qdisc registration error \n");
return -EINVAL;
}
nf_registered++;
-
- if (nf_register_hook(&ing6_ops) < 0) {
- printk("IPv6 ingress qdisc registration error, " \
- "disabling IPv6 support.\n");
- } else
- nf_registered++;
}
#endif
-#endif
-
- DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
- p->q = &noop_qdisc;
return 0;
}
-
-static void ingress_reset(struct Qdisc *sch)
-{
- struct ingress_qdisc_data *p = PRIV(sch);
-
- DPRINTK("ingress_reset(sch %p,[qdisc %p])\n", sch, p);
-
-/*
-#if 0
-*/
-/* for future use */
- qdisc_reset(p->q);
-/*
-#endif
-*/
-}
-
-/* ------------------------------------------------------------- */
-
-
/* ------------------------------------------------------------- */
static void ingress_destroy(struct Qdisc *sch)
{
- struct ingress_qdisc_data *p = PRIV(sch);
+ struct ingress_qdisc_data *p = qdisc_priv(sch);
- DPRINTK("ingress_destroy(sch %p,[qdisc %p])\n", sch, p);
tcf_destroy_chain(p->filter_list);
-#if 0
-/* for future use */
- qdisc_destroy(p->q);
-#endif
}
-
static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
{
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
- rta = (struct rtattr *) b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
- rta->rta_len = skb_tail_pointer(skb) - b;
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
+ nla_nest_end(skb, nest);
return skb->len;
-rtattr_failure:
- nlmsg_trim(skb, b);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
return -1;
}
-static struct Qdisc_class_ops ingress_class_ops = {
+static const struct Qdisc_class_ops ingress_class_ops = {
.graft = ingress_graft,
.leaf = ingress_leaf,
.get = ingress_get,
.put = ingress_put,
.change = ingress_change,
- .delete = NULL,
.walk = ingress_walk,
.tcf_chain = ingress_find_tcf,
.bind_tcf = ingress_bind_filter,
.unbind_tcf = ingress_put,
- .dump = NULL,
};
-static struct Qdisc_ops ingress_qdisc_ops = {
- .next = NULL,
+static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
.cl_ops = &ingress_class_ops,
.id = "ingress",
.priv_size = sizeof(struct ingress_qdisc_data),
.enqueue = ingress_enqueue,
- .dequeue = ingress_dequeue,
- .requeue = ingress_requeue,
- .drop = ingress_drop,
.init = ingress_init,
- .reset = ingress_reset,
.destroy = ingress_destroy,
- .change = NULL,
.dump = ingress_dump,
.owner = THIS_MODULE,
};
static int __init ingress_module_init(void)
{
- int ret = 0;
-
- if ((ret = register_qdisc(&ingress_qdisc_ops)) < 0) {
- printk("Unable to register Ingress qdisc\n");
- return ret;
- }
-
- return ret;
+ return register_qdisc(&ingress_qdisc_ops);
}
+
static void __exit ingress_module_exit(void)
{
unregister_qdisc(&ingress_qdisc_ops);
-#ifndef CONFIG_NET_CLS_ACT
-#ifdef CONFIG_NETFILTER
- if (nf_registered) {
- nf_unregister_hook(&ing_ops);
- if (nf_registered > 1)
- nf_unregister_hook(&ing6_ops);
- }
-#endif
+#if !defined(CONFIG_NET_CLS_ACT) && defined(CONFIG_NETFILTER)
+ if (nf_registered)
+ nf_unregister_hooks(ing_ops, ARRAY_SIZE(ing_ops));
#endif
}
+
module_init(ingress_module_init)
module_exit(ingress_module_exit)
MODULE_LICENSE("GPL");
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 9e5e87e..c9c649b 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -313,21 +313,21 @@ static void netem_reset(struct Qdisc *sch)
/* Pass size change message down to embedded FIFO */
static int set_fifo_limit(struct Qdisc *q, int limit)
{
- struct rtattr *rta;
+ struct nlattr *nla;
int ret = -ENOMEM;
/* Hack to avoid sending change message to non-FIFO */
if (strncmp(q->ops->id + 1, "fifo", 4) != 0)
return 0;
- rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
- if (rta) {
- rta->rta_type = RTM_NEWQDISC;
- rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
- ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
+ nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
+ if (nla) {
+ nla->nla_type = RTM_NEWQDISC;
+ nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt));
+ ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit;
- ret = q->ops->change(q, rta);
- kfree(rta);
+ ret = q->ops->change(q, nla);
+ kfree(nla);
}
return ret;
}
@@ -336,11 +336,11 @@ static int set_fifo_limit(struct Qdisc *q, int limit)
* Distribution data is a variable size payload containing
* signed 16 bit values.
*/
-static int get_dist_table(struct Qdisc *sch, const struct rtattr *attr)
+static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
{
struct netem_sched_data *q = qdisc_priv(sch);
- unsigned long n = RTA_PAYLOAD(attr)/sizeof(__s16);
- const __s16 *data = RTA_DATA(attr);
+ unsigned long n = nla_len(attr)/sizeof(__s16);
+ const __s16 *data = nla_data(attr);
struct disttable *d;
int i;
@@ -363,13 +363,10 @@ static int get_dist_table(struct Qdisc *sch, const struct rtattr *attr)
return 0;
}
-static int get_correlation(struct Qdisc *sch, const struct rtattr *attr)
+static int get_correlation(struct Qdisc *sch, const struct nlattr *attr)
{
struct netem_sched_data *q = qdisc_priv(sch);
- const struct tc_netem_corr *c = RTA_DATA(attr);
-
- if (RTA_PAYLOAD(attr) != sizeof(*c))
- return -EINVAL;
+ const struct tc_netem_corr *c = nla_data(attr);
init_crandom(&q->delay_cor, c->delay_corr);
init_crandom(&q->loss_cor, c->loss_corr);
@@ -377,43 +374,48 @@ static int get_correlation(struct Qdisc *sch, const struct rtattr *attr)
return 0;
}
-static int get_reorder(struct Qdisc *sch, const struct rtattr *attr)
+static int get_reorder(struct Qdisc *sch, const struct nlattr *attr)
{
struct netem_sched_data *q = qdisc_priv(sch);
- const struct tc_netem_reorder *r = RTA_DATA(attr);
-
- if (RTA_PAYLOAD(attr) != sizeof(*r))
- return -EINVAL;
+ const struct tc_netem_reorder *r = nla_data(attr);
q->reorder = r->probability;
init_crandom(&q->reorder_cor, r->correlation);
return 0;
}
-static int get_corrupt(struct Qdisc *sch, const struct rtattr *attr)
+static int get_corrupt(struct Qdisc *sch, const struct nlattr *attr)
{
struct netem_sched_data *q = qdisc_priv(sch);
- const struct tc_netem_corrupt *r = RTA_DATA(attr);
-
- if (RTA_PAYLOAD(attr) != sizeof(*r))
- return -EINVAL;
+ const struct tc_netem_corrupt *r = nla_data(attr);
q->corrupt = r->probability;
init_crandom(&q->corrupt_cor, r->correlation);
return 0;
}
+static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
+ [TCA_NETEM_CORR] = { .len = sizeof(struct tc_netem_corr) },
+ [TCA_NETEM_REORDER] = { .len = sizeof(struct tc_netem_reorder) },
+ [TCA_NETEM_CORRUPT] = { .len = sizeof(struct tc_netem_corrupt) },
+};
+
/* Parse netlink message to set options */
-static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+static int netem_change(struct Qdisc *sch, struct nlattr *opt)
{
struct netem_sched_data *q = qdisc_priv(sch);
+ struct nlattr *tb[TCA_NETEM_MAX + 1];
struct tc_netem_qopt *qopt;
int ret;
- if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
+ if (opt == NULL)
return -EINVAL;
- qopt = RTA_DATA(opt);
+ ret = nla_parse_nested_compat(tb, TCA_NETEM_MAX, opt, netem_policy,
+ qopt, sizeof(*qopt));
+ if (ret < 0)
+ return ret;
+
ret = set_fifo_limit(q->qdisc, qopt->limit);
if (ret) {
pr_debug("netem: can't set fifo limit\n");
@@ -434,39 +436,28 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt)
if (q->gap)
q->reorder = ~0;
- /* Handle nested options after initial queue options.
- * Should have put all options in nested format but too late now.
- */
- if (RTA_PAYLOAD(opt) > sizeof(*qopt)) {
- struct rtattr *tb[TCA_NETEM_MAX];
- if (rtattr_parse(tb, TCA_NETEM_MAX,
- RTA_DATA(opt) + sizeof(*qopt),
- RTA_PAYLOAD(opt) - sizeof(*qopt)))
- return -EINVAL;
-
- if (tb[TCA_NETEM_CORR-1]) {
- ret = get_correlation(sch, tb[TCA_NETEM_CORR-1]);
- if (ret)
- return ret;
- }
+ if (tb[TCA_NETEM_CORR]) {
+ ret = get_correlation(sch, tb[TCA_NETEM_CORR]);
+ if (ret)
+ return ret;
+ }
- if (tb[TCA_NETEM_DELAY_DIST-1]) {
- ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST-1]);
- if (ret)
- return ret;
- }
+ if (tb[TCA_NETEM_DELAY_DIST]) {
+ ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]);
+ if (ret)
+ return ret;
+ }
- if (tb[TCA_NETEM_REORDER-1]) {
- ret = get_reorder(sch, tb[TCA_NETEM_REORDER-1]);
- if (ret)
- return ret;
- }
+ if (tb[TCA_NETEM_REORDER]) {
+ ret = get_reorder(sch, tb[TCA_NETEM_REORDER]);
+ if (ret)
+ return ret;
+ }
- if (tb[TCA_NETEM_CORRUPT-1]) {
- ret = get_corrupt(sch, tb[TCA_NETEM_CORRUPT-1]);
- if (ret)
- return ret;
- }
+ if (tb[TCA_NETEM_CORRUPT]) {
+ ret = get_corrupt(sch, tb[TCA_NETEM_CORRUPT]);
+ if (ret)
+ return ret;
}
return 0;
@@ -515,13 +506,13 @@ static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
return qdisc_reshape_fail(nskb, sch);
}
-static int tfifo_init(struct Qdisc *sch, struct rtattr *opt)
+static int tfifo_init(struct Qdisc *sch, struct nlattr *opt)
{
struct fifo_sched_data *q = qdisc_priv(sch);
if (opt) {
- struct tc_fifo_qopt *ctl = RTA_DATA(opt);
- if (RTA_PAYLOAD(opt) < sizeof(*ctl))
+ struct tc_fifo_qopt *ctl = nla_data(opt);
+ if (nla_len(opt) < sizeof(*ctl))
return -EINVAL;
q->limit = ctl->limit;
@@ -537,14 +528,14 @@ static int tfifo_dump(struct Qdisc *sch, struct sk_buff *skb)
struct fifo_sched_data *q = qdisc_priv(sch);
struct tc_fifo_qopt opt = { .limit = q->limit };
- RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
return skb->len;
-rtattr_failure:
+nla_put_failure:
return -1;
}
-static struct Qdisc_ops tfifo_qdisc_ops = {
+static struct Qdisc_ops tfifo_qdisc_ops __read_mostly = {
.id = "tfifo",
.priv_size = sizeof(struct fifo_sched_data),
.enqueue = tfifo_enqueue,
@@ -557,7 +548,7 @@ static struct Qdisc_ops tfifo_qdisc_ops = {
.dump = tfifo_dump,
};
-static int netem_init(struct Qdisc *sch, struct rtattr *opt)
+static int netem_init(struct Qdisc *sch, struct nlattr *opt)
{
struct netem_sched_data *q = qdisc_priv(sch);
int ret;
@@ -595,7 +586,7 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
{
const struct netem_sched_data *q = qdisc_priv(sch);
unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta = (struct rtattr *) b;
+ struct nlattr *nla = (struct nlattr *) b;
struct tc_netem_qopt qopt;
struct tc_netem_corr cor;
struct tc_netem_reorder reorder;
@@ -607,26 +598,26 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
qopt.loss = q->loss;
qopt.gap = q->gap;
qopt.duplicate = q->duplicate;
- RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
+ NLA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
cor.delay_corr = q->delay_cor.rho;
cor.loss_corr = q->loss_cor.rho;
cor.dup_corr = q->dup_cor.rho;
- RTA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor);
+ NLA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor);
reorder.probability = q->reorder;
reorder.correlation = q->reorder_cor.rho;
- RTA_PUT(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder);
+ NLA_PUT(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder);
corrupt.probability = q->corrupt;
corrupt.correlation = q->corrupt_cor.rho;
- RTA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
+ NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
- rta->rta_len = skb_tail_pointer(skb) - b;
+ nla->nla_len = skb_tail_pointer(skb) - b;
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -678,7 +669,7 @@ static void netem_put(struct Qdisc *sch, unsigned long arg)
}
static int netem_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
- struct rtattr **tca, unsigned long *arg)
+ struct nlattr **tca, unsigned long *arg)
{
return -ENOSYS;
}
@@ -705,7 +696,7 @@ static struct tcf_proto **netem_find_tcf(struct Qdisc *sch, unsigned long cl)
return NULL;
}
-static struct Qdisc_class_ops netem_class_ops = {
+static const struct Qdisc_class_ops netem_class_ops = {
.graft = netem_graft,
.leaf = netem_leaf,
.get = netem_get,
@@ -717,7 +708,7 @@ static struct Qdisc_class_ops netem_class_ops = {
.dump = netem_dump_class,
};
-static struct Qdisc_ops netem_qdisc_ops = {
+static struct Qdisc_ops netem_qdisc_ops __read_mostly = {
.id = "netem",
.cl_ops = &netem_class_ops,
.priv_size = sizeof(struct netem_sched_data),
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index de89409..4aa2b45 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -224,16 +224,19 @@ prio_destroy(struct Qdisc* sch)
qdisc_destroy(q->queues[prio]);
}
-static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
+static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
{
struct prio_sched_data *q = qdisc_priv(sch);
struct tc_prio_qopt *qopt;
- struct rtattr *tb[TCA_PRIO_MAX];
+ struct nlattr *tb[TCA_PRIO_MAX + 1];
+ int err;
int i;
- if (rtattr_parse_nested_compat(tb, TCA_PRIO_MAX, opt, qopt,
- sizeof(*qopt)))
- return -EINVAL;
+ err = nla_parse_nested_compat(tb, TCA_PRIO_MAX, opt, NULL, qopt,
+ sizeof(*qopt));
+ if (err < 0)
+ return err;
+
q->bands = qopt->bands;
/* If we're multiqueue, make sure the number of incoming bands
* matches the number of queues on the device we're associating with.
@@ -242,7 +245,7 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
* only one that is enabled for multiqueue, since it's the only one
* that interacts with the underlying device.
*/
- q->mq = RTA_GET_FLAG(tb[TCA_PRIO_MQ - 1]);
+ q->mq = nla_get_flag(tb[TCA_PRIO_MQ]);
if (q->mq) {
if (sch->parent != TC_H_ROOT)
return -EINVAL;
@@ -296,7 +299,7 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
return 0;
}
-static int prio_init(struct Qdisc *sch, struct rtattr *opt)
+static int prio_init(struct Qdisc *sch, struct nlattr *opt)
{
struct prio_sched_data *q = qdisc_priv(sch);
int i;
@@ -319,20 +322,24 @@ static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct prio_sched_data *q = qdisc_priv(sch);
unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *nest;
+ struct nlattr *nest;
struct tc_prio_qopt opt;
opt.bands = q->bands;
memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX+1);
- nest = RTA_NEST_COMPAT(skb, TCA_OPTIONS, sizeof(opt), &opt);
- if (q->mq)
- RTA_PUT_FLAG(skb, TCA_PRIO_MQ);
- RTA_NEST_COMPAT_END(skb, nest);
+ nest = nla_nest_compat_start(skb, TCA_OPTIONS, sizeof(opt), &opt);
+ if (nest == NULL)
+ goto nla_put_failure;
+ if (q->mq) {
+ if (nla_put_flag(skb, TCA_PRIO_MQ) < 0)
+ goto nla_put_failure;
+ }
+ nla_nest_compat_end(skb, nest);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -392,7 +399,7 @@ static void prio_put(struct Qdisc *q, unsigned long cl)
return;
}
-static int prio_change(struct Qdisc *sch, u32 handle, u32 parent, struct rtattr **tca, unsigned long *arg)
+static int prio_change(struct Qdisc *sch, u32 handle, u32 parent, struct nlattr **tca, unsigned long *arg)
{
unsigned long cl = *arg;
struct prio_sched_data *q = qdisc_priv(sch);
@@ -468,7 +475,7 @@ static struct tcf_proto ** prio_find_tcf(struct Qdisc *sch, unsigned long cl)
return &q->filter_list;
}
-static struct Qdisc_class_ops prio_class_ops = {
+static const struct Qdisc_class_ops prio_class_ops = {
.graft = prio_graft,
.leaf = prio_leaf,
.get = prio_get,
@@ -483,7 +490,7 @@ static struct Qdisc_class_ops prio_class_ops = {
.dump_stats = prio_dump_class_stats,
};
-static struct Qdisc_ops prio_qdisc_ops = {
+static struct Qdisc_ops prio_qdisc_ops __read_mostly = {
.next = NULL,
.cl_ops = &prio_class_ops,
.id = "prio",
@@ -500,7 +507,7 @@ static struct Qdisc_ops prio_qdisc_ops = {
.owner = THIS_MODULE,
};
-static struct Qdisc_ops rr_qdisc_ops = {
+static struct Qdisc_ops rr_qdisc_ops __read_mostly = {
.next = NULL,
.cl_ops = &prio_class_ops,
.id = "rr",
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 9b95fef..3dcd493 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -177,21 +177,21 @@ static void red_destroy(struct Qdisc *sch)
static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit)
{
struct Qdisc *q;
- struct rtattr *rta;
+ struct nlattr *nla;
int ret;
q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops,
TC_H_MAKE(sch->handle, 1));
if (q) {
- rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)),
+ nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)),
GFP_KERNEL);
- if (rta) {
- rta->rta_type = RTM_NEWQDISC;
- rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
- ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
+ if (nla) {
+ nla->nla_type = RTM_NEWQDISC;
+ nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt));
+ ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit;
- ret = q->ops->change(q, rta);
- kfree(rta);
+ ret = q->ops->change(q, nla);
+ kfree(nla);
if (ret == 0)
return q;
@@ -201,23 +201,31 @@ static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit)
return NULL;
}
-static int red_change(struct Qdisc *sch, struct rtattr *opt)
+static const struct nla_policy red_policy[TCA_RED_MAX + 1] = {
+ [TCA_RED_PARMS] = { .len = sizeof(struct tc_red_qopt) },
+ [TCA_RED_STAB] = { .len = RED_STAB_SIZE },
+};
+
+static int red_change(struct Qdisc *sch, struct nlattr *opt)
{
struct red_sched_data *q = qdisc_priv(sch);
- struct rtattr *tb[TCA_RED_MAX];
+ struct nlattr *tb[TCA_RED_MAX + 1];
struct tc_red_qopt *ctl;
struct Qdisc *child = NULL;
+ int err;
- if (opt == NULL || rtattr_parse_nested(tb, TCA_RED_MAX, opt))
+ if (opt == NULL)
return -EINVAL;
- if (tb[TCA_RED_PARMS-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_RED_PARMS-1]) < sizeof(*ctl) ||
- tb[TCA_RED_STAB-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_RED_STAB-1]) < RED_STAB_SIZE)
+ err = nla_parse_nested(tb, TCA_RED_MAX, opt, red_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_RED_PARMS] == NULL ||
+ tb[TCA_RED_STAB] == NULL)
return -EINVAL;
- ctl = RTA_DATA(tb[TCA_RED_PARMS-1]);
+ ctl = nla_data(tb[TCA_RED_PARMS]);
if (ctl->limit > 0) {
child = red_create_dflt(sch, ctl->limit);
@@ -235,7 +243,7 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog,
ctl->Plog, ctl->Scell_log,
- RTA_DATA(tb[TCA_RED_STAB-1]));
+ nla_data(tb[TCA_RED_STAB]));
if (skb_queue_empty(&sch->q))
red_end_of_idle_period(&q->parms);
@@ -244,7 +252,7 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
return 0;
}
-static int red_init(struct Qdisc* sch, struct rtattr *opt)
+static int red_init(struct Qdisc* sch, struct nlattr *opt)
{
struct red_sched_data *q = qdisc_priv(sch);
@@ -255,7 +263,7 @@ static int red_init(struct Qdisc* sch, struct rtattr *opt)
static int red_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct red_sched_data *q = qdisc_priv(sch);
- struct rtattr *opts = NULL;
+ struct nlattr *opts = NULL;
struct tc_red_qopt opt = {
.limit = q->limit,
.flags = q->flags,
@@ -266,12 +274,14 @@ static int red_dump(struct Qdisc *sch, struct sk_buff *skb)
.Scell_log = q->parms.Scell_log,
};
- opts = RTA_NEST(skb, TCA_OPTIONS);
- RTA_PUT(skb, TCA_RED_PARMS, sizeof(opt), &opt);
- return RTA_NEST_END(skb, opts);
+ opts = nla_nest_start(skb, TCA_OPTIONS);
+ if (opts == NULL)
+ goto nla_put_failure;
+ NLA_PUT(skb, TCA_RED_PARMS, sizeof(opt), &opt);
+ return nla_nest_end(skb, opts);
-rtattr_failure:
- return RTA_NEST_CANCEL(skb, opts);
+nla_put_failure:
+ return nla_nest_cancel(skb, opts);
}
static int red_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
@@ -332,7 +342,7 @@ static void red_put(struct Qdisc *sch, unsigned long arg)
}
static int red_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
- struct rtattr **tca, unsigned long *arg)
+ struct nlattr **tca, unsigned long *arg)
{
return -ENOSYS;
}
@@ -359,7 +369,7 @@ static struct tcf_proto **red_find_tcf(struct Qdisc *sch, unsigned long cl)
return NULL;
}
-static struct Qdisc_class_ops red_class_ops = {
+static const struct Qdisc_class_ops red_class_ops = {
.graft = red_graft,
.leaf = red_leaf,
.get = red_get,
@@ -371,7 +381,7 @@ static struct Qdisc_class_ops red_class_ops = {
.dump = red_dump_class,
};
-static struct Qdisc_ops red_qdisc_ops = {
+static struct Qdisc_ops red_qdisc_ops __read_mostly = {
.id = "red",
.priv_size = sizeof(struct red_sched_data),
.cl_ops = &red_class_ops,
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index b542c87..91af539 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -122,7 +122,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
{
const struct iphdr *iph = ip_hdr(skb);
h = iph->daddr;
- h2 = iph->saddr^iph->protocol;
+ h2 = iph->saddr ^ iph->protocol;
if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
(iph->protocol == IPPROTO_TCP ||
iph->protocol == IPPROTO_UDP ||
@@ -137,7 +137,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
{
struct ipv6hdr *iph = ipv6_hdr(skb);
h = iph->daddr.s6_addr32[3];
- h2 = iph->saddr.s6_addr32[3]^iph->nexthdr;
+ h2 = iph->saddr.s6_addr32[3] ^ iph->nexthdr;
if (iph->nexthdr == IPPROTO_TCP ||
iph->nexthdr == IPPROTO_UDP ||
iph->nexthdr == IPPROTO_UDPLITE ||
@@ -148,9 +148,10 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
break;
}
default:
- h = (u32)(unsigned long)skb->dst^skb->protocol;
- h2 = (u32)(unsigned long)skb->sk;
+ h = (unsigned long)skb->dst ^ skb->protocol;
+ h2 = (unsigned long)skb->sk;
}
+
return sfq_fold_hash(q, h, h2);
}
@@ -208,7 +209,7 @@ static unsigned int sfq_drop(struct Qdisc *sch)
drop a packet from it */
if (d > 1) {
- sfq_index x = q->dep[d+SFQ_DEPTH].next;
+ sfq_index x = q->dep[d + SFQ_DEPTH].next;
skb = q->qs[x].prev;
len = skb->len;
__skb_unlink(skb, &q->qs[x]);
@@ -241,7 +242,7 @@ static unsigned int sfq_drop(struct Qdisc *sch)
}
static int
-sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct sfq_sched_data *q = qdisc_priv(sch);
unsigned hash = sfq_hash(q, skb);
@@ -252,6 +253,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
q->ht[hash] = x = q->dep[SFQ_DEPTH].next;
q->hash[x] = hash;
}
+
/* If selected queue has length q->limit, this means that
* all another queues are empty and that we do simple tail drop,
* i.e. drop _this_ packet.
@@ -284,7 +286,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
}
static int
-sfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
+sfq_requeue(struct sk_buff *skb, struct Qdisc *sch)
{
struct sfq_sched_data *q = qdisc_priv(sch);
unsigned hash = sfq_hash(q, skb);
@@ -295,6 +297,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
q->ht[hash] = x = q->dep[SFQ_DEPTH].next;
q->hash[x] = hash;
}
+
sch->qstats.backlog += skb->len;
__skb_queue_head(&q->qs[x], skb);
/* If selected queue has length q->limit+1, this means that
@@ -310,6 +313,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
kfree_skb(skb);
return NET_XMIT_CN;
}
+
sfq_inc(q, x);
if (q->qs[x].qlen == 1) { /* The flow is new */
if (q->tail == SFQ_DEPTH) { /* It is the first flow */
@@ -322,6 +326,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
q->tail = x;
}
}
+
if (++sch->q.qlen <= q->limit) {
sch->qstats.requeues++;
return 0;
@@ -336,7 +341,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
static struct sk_buff *
-sfq_dequeue(struct Qdisc* sch)
+sfq_dequeue(struct Qdisc *sch)
{
struct sfq_sched_data *q = qdisc_priv(sch);
struct sk_buff *skb;
@@ -373,7 +378,7 @@ sfq_dequeue(struct Qdisc* sch)
}
static void
-sfq_reset(struct Qdisc* sch)
+sfq_reset(struct Qdisc *sch)
{
struct sk_buff *skb;
@@ -383,27 +388,27 @@ sfq_reset(struct Qdisc* sch)
static void sfq_perturbation(unsigned long arg)
{
- struct Qdisc *sch = (struct Qdisc*)arg;
+ struct Qdisc *sch = (struct Qdisc *)arg;
struct sfq_sched_data *q = qdisc_priv(sch);
- get_random_bytes(&q->perturbation, 4);
+ q->perturbation = net_random();
if (q->perturb_period)
mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
}
-static int sfq_change(struct Qdisc *sch, struct rtattr *opt)
+static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
{
struct sfq_sched_data *q = qdisc_priv(sch);
- struct tc_sfq_qopt *ctl = RTA_DATA(opt);
+ struct tc_sfq_qopt *ctl = nla_data(opt);
unsigned int qlen;
- if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
+ if (opt->nla_len < nla_attr_size(sizeof(*ctl)))
return -EINVAL;
sch_tree_lock(sch);
q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
- q->perturb_period = ctl->perturb_period*HZ;
+ q->perturb_period = ctl->perturb_period * HZ;
if (ctl->limit)
q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 1);
@@ -415,41 +420,44 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt)
del_timer(&q->perturb_timer);
if (q->perturb_period) {
mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
- get_random_bytes(&q->perturbation, 4);
+ q->perturbation = net_random();
}
sch_tree_unlock(sch);
return 0;
}
-static int sfq_init(struct Qdisc *sch, struct rtattr *opt)
+static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
{
struct sfq_sched_data *q = qdisc_priv(sch);
int i;
- init_timer(&q->perturb_timer);
- q->perturb_timer.data = (unsigned long)sch;
q->perturb_timer.function = sfq_perturbation;
+ q->perturb_timer.data = (unsigned long)sch;;
+ init_timer_deferrable(&q->perturb_timer);
- for (i=0; i<SFQ_HASH_DIVISOR; i++)
+ for (i = 0; i < SFQ_HASH_DIVISOR; i++)
q->ht[i] = SFQ_DEPTH;
- for (i=0; i<SFQ_DEPTH; i++) {
+
+ for (i = 0; i < SFQ_DEPTH; i++) {
skb_queue_head_init(&q->qs[i]);
- q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH;
- q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH;
+ q->dep[i + SFQ_DEPTH].next = i + SFQ_DEPTH;
+ q->dep[i + SFQ_DEPTH].prev = i + SFQ_DEPTH;
}
+
q->limit = SFQ_DEPTH - 1;
q->max_depth = 0;
q->tail = SFQ_DEPTH;
if (opt == NULL) {
q->quantum = psched_mtu(sch->dev);
q->perturb_period = 0;
- get_random_bytes(&q->perturbation, 4);
+ q->perturbation = net_random();
} else {
int err = sfq_change(sch, opt);
if (err)
return err;
}
- for (i=0; i<SFQ_DEPTH; i++)
+
+ for (i = 0; i < SFQ_DEPTH; i++)
sfq_link(q, i);
return 0;
}
@@ -467,22 +475,22 @@ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
struct tc_sfq_qopt opt;
opt.quantum = q->quantum;
- opt.perturb_period = q->perturb_period/HZ;
+ opt.perturb_period = q->perturb_period / HZ;
opt.limit = q->limit;
opt.divisor = SFQ_HASH_DIVISOR;
opt.flows = q->limit;
- RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
-static struct Qdisc_ops sfq_qdisc_ops = {
+static struct Qdisc_ops sfq_qdisc_ops __read_mostly = {
.next = NULL,
.cl_ops = NULL,
.id = "sfq",
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index b0d8109..0b7d78f 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -245,20 +245,21 @@ static void tbf_reset(struct Qdisc* sch)
static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit)
{
struct Qdisc *q;
- struct rtattr *rta;
+ struct nlattr *nla;
int ret;
q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops,
TC_H_MAKE(sch->handle, 1));
if (q) {
- rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
- if (rta) {
- rta->rta_type = RTM_NEWQDISC;
- rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
- ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
+ nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)),
+ GFP_KERNEL);
+ if (nla) {
+ nla->nla_type = RTM_NEWQDISC;
+ nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt));
+ ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit;
- ret = q->ops->change(q, rta);
- kfree(rta);
+ ret = q->ops->change(q, nla);
+ kfree(nla);
if (ret == 0)
return q;
@@ -269,30 +270,39 @@ static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit)
return NULL;
}
-static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
+static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = {
+ [TCA_TBF_PARMS] = { .len = sizeof(struct tc_tbf_qopt) },
+ [TCA_TBF_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+ [TCA_TBF_PTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+};
+
+static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
{
- int err = -EINVAL;
+ int err;
struct tbf_sched_data *q = qdisc_priv(sch);
- struct rtattr *tb[TCA_TBF_PTAB];
+ struct nlattr *tb[TCA_TBF_PTAB + 1];
struct tc_tbf_qopt *qopt;
struct qdisc_rate_table *rtab = NULL;
struct qdisc_rate_table *ptab = NULL;
struct Qdisc *child = NULL;
int max_size,n;
- if (rtattr_parse_nested(tb, TCA_TBF_PTAB, opt) ||
- tb[TCA_TBF_PARMS-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_TBF_PARMS-1]) < sizeof(*qopt))
+ err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy);
+ if (err < 0)
+ return err;
+
+ err = -EINVAL;
+ if (tb[TCA_TBF_PARMS] == NULL)
goto done;
- qopt = RTA_DATA(tb[TCA_TBF_PARMS-1]);
- rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB-1]);
+ qopt = nla_data(tb[TCA_TBF_PARMS]);
+ rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB]);
if (rtab == NULL)
goto done;
if (qopt->peakrate.rate) {
if (qopt->peakrate.rate > qopt->rate.rate)
- ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB-1]);
+ ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB]);
if (ptab == NULL)
goto done;
}
@@ -339,7 +349,7 @@ done:
return err;
}
-static int tbf_init(struct Qdisc* sch, struct rtattr *opt)
+static int tbf_init(struct Qdisc* sch, struct nlattr *opt)
{
struct tbf_sched_data *q = qdisc_priv(sch);
@@ -370,12 +380,12 @@ static void tbf_destroy(struct Qdisc *sch)
static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct tbf_sched_data *q = qdisc_priv(sch);
- unsigned char *b = skb_tail_pointer(skb);
- struct rtattr *rta;
+ struct nlattr *nest;
struct tc_tbf_qopt opt;
- rta = (struct rtattr*)b;
- RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
opt.limit = q->limit;
opt.rate = q->R_tab->rate;
@@ -385,13 +395,13 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb)
memset(&opt.peakrate, 0, sizeof(opt.peakrate));
opt.mtu = q->mtu;
opt.buffer = q->buffer;
- RTA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt);
- rta->rta_len = skb_tail_pointer(skb) - b;
+ NLA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt);
+ nla_nest_end(skb, nest);
return skb->len;
-rtattr_failure:
- nlmsg_trim(skb, b);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
return -1;
}
@@ -442,7 +452,7 @@ static void tbf_put(struct Qdisc *sch, unsigned long arg)
}
static int tbf_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
- struct rtattr **tca, unsigned long *arg)
+ struct nlattr **tca, unsigned long *arg)
{
return -ENOSYS;
}
@@ -469,7 +479,7 @@ static struct tcf_proto **tbf_find_tcf(struct Qdisc *sch, unsigned long cl)
return NULL;
}
-static struct Qdisc_class_ops tbf_class_ops =
+static const struct Qdisc_class_ops tbf_class_ops =
{
.graft = tbf_graft,
.leaf = tbf_leaf,
@@ -482,7 +492,7 @@ static struct Qdisc_class_ops tbf_class_ops =
.dump = tbf_dump_class,
};
-static struct Qdisc_ops tbf_qdisc_ops = {
+static struct Qdisc_ops tbf_qdisc_ops __read_mostly = {
.next = NULL,
.cl_ops = &tbf_class_ops,
.id = "tbf",
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index c0ed06d..1411c7b1 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -168,7 +168,7 @@ teql_destroy(struct Qdisc* sch)
}
}
-static int teql_qdisc_init(struct Qdisc *sch, struct rtattr *opt)
+static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt)
{
struct net_device *dev = sch->dev;
struct teql_master *m = (struct teql_master*)sch->ops;