Commit 73a842ed authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller

[PKT_SCHED]: cls_fw: Use generic routines to configure action/policer

Adds a new function fw_change_attr using the new generic routines which
can be used to change attribute but also to initially set them to avoid
duplicated code.
Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 15e35860
...@@ -155,11 +155,8 @@ static void fw_destroy(struct tcf_proto *tp) ...@@ -155,11 +155,8 @@ static void fw_destroy(struct tcf_proto *tp)
for (h=0; h<256; h++) { for (h=0; h<256; h++) {
while ((f=head->ht[h]) != NULL) { while ((f=head->ht[h]) != NULL) {
unsigned long cl;
head->ht[h] = f->next; head->ht[h] = f->next;
tcf_unbind_filter(tp, &f->res);
if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
#ifdef CONFIG_NET_CLS_ACT #ifdef CONFIG_NET_CLS_ACT
if (f->action) { if (f->action) {
tcf_action_destroy(f->action,TCA_ACT_UNBIND); tcf_action_destroy(f->action,TCA_ACT_UNBIND);
...@@ -187,14 +184,10 @@ static int fw_delete(struct tcf_proto *tp, unsigned long arg) ...@@ -187,14 +184,10 @@ static int fw_delete(struct tcf_proto *tp, unsigned long arg)
for (fp=&head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) { for (fp=&head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) {
if (*fp == f) { if (*fp == f) {
unsigned long cl;
tcf_tree_lock(tp); tcf_tree_lock(tp);
*fp = f->next; *fp = f->next;
tcf_tree_unlock(tp); tcf_tree_unlock(tp);
tcf_unbind_filter(tp, &f->res);
if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0)
tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
#ifdef CONFIG_NET_CLS_ACT #ifdef CONFIG_NET_CLS_ACT
if (f->action) { if (f->action) {
tcf_action_destroy(f->action,TCA_ACT_UNBIND); tcf_action_destroy(f->action,TCA_ACT_UNBIND);
...@@ -212,21 +205,67 @@ static int fw_delete(struct tcf_proto *tp, unsigned long arg) ...@@ -212,21 +205,67 @@ static int fw_delete(struct tcf_proto *tp, unsigned long arg)
return -EINVAL; return -EINVAL;
} }
static int
fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
struct rtattr **tb, struct rtattr **tca, unsigned long base)
{
int 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]);
tcf_bind_filter(tp, &f->res, base);
}
#ifdef CONFIG_NET_CLS_ACT
if (tb[TCA_FW_POLICE-1]) {
err = tcf_change_act_police(tp, &f->action, tb[TCA_FW_POLICE-1],
tca[TCA_RATE-1]);
if (err < 0)
goto errout;
}
if (tb[TCA_FW_ACT-1]) {
err = tcf_change_act(tp, &f->action, tb[TCA_FW_ACT-1],
tca[TCA_RATE-1]);
if (err < 0)
goto errout;
}
#ifdef CONFIG_NET_CLS_IND
if (tb[TCA_FW_INDEV-1]) {
err = tcf_change_indev(tp, f->indev, tb[TCA_FW_INDEV-1]);
if (err < 0)
goto errout;
}
#endif /* CONFIG_NET_CLS_IND */
#else /* CONFIG_NET_CLS_ACT */
#ifdef CONFIG_NET_CLS_POLICE
if (tb[TCA_FW_POLICE-1]) {
err = tcf_change_police(tp, &f->police, tb[TCA_FW_POLICE-1],
tca[TCA_RATE-1]);
if (err < 0)
goto errout;
}
#endif /* CONFIG_NET_CLS_POLICE */
#endif /* CONFIG_NET_CLS_ACT */
err = 0;
errout:
return err;
}
static int fw_change(struct tcf_proto *tp, unsigned long base, static int fw_change(struct tcf_proto *tp, unsigned long base,
u32 handle, u32 handle,
struct rtattr **tca, struct rtattr **tca,
unsigned long *arg) unsigned long *arg)
{ {
struct fw_head *head = (struct fw_head*)tp->root; struct fw_head *head = (struct fw_head*)tp->root;
struct fw_filter *f; struct fw_filter *f = (struct fw_filter *) *arg;
struct rtattr *opt = tca[TCA_OPTIONS-1]; struct rtattr *opt = tca[TCA_OPTIONS-1];
struct rtattr *tb[TCA_FW_MAX]; struct rtattr *tb[TCA_FW_MAX];
int err; int err;
#ifdef CONFIG_NET_CLS_ACT
struct tc_action *act = NULL;
int ret;
#endif
if (!opt) if (!opt)
return handle ? -EINVAL : 0; return handle ? -EINVAL : 0;
...@@ -234,85 +273,10 @@ static int fw_change(struct tcf_proto *tp, unsigned long base, ...@@ -234,85 +273,10 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
if (rtattr_parse(tb, TCA_FW_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0) if (rtattr_parse(tb, TCA_FW_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0)
return -EINVAL; return -EINVAL;
if ((f = (struct fw_filter*)*arg) != NULL) { if (f != NULL) {
/* Node exists: adjust only classid */
if (f->id != handle && handle) if (f->id != handle && handle)
return -EINVAL; return -EINVAL;
if (tb[TCA_FW_CLASSID-1]) { return fw_change_attrs(tp, f, tb, tca, base);
unsigned long cl;
f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]);
cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid);
cl = cls_set_class(tp, &f->res.class, cl);
if (cl)
tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
}
#ifdef CONFIG_NET_CLS_ACT
if (tb[TCA_FW_POLICE-1]) {
act = kmalloc(sizeof(*act),GFP_KERNEL);
if (NULL == act)
return -ENOMEM;
memset(act,0,sizeof(*act));
ret = tcf_action_init_1(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1] ,act,"police",TCA_ACT_NOREPLACE,TCA_ACT_BIND);
if (0 > ret){
tcf_action_destroy(act,TCA_ACT_UNBIND);
return ret;
}
act->type = TCA_OLD_COMPAT;
sch_tree_lock(tp->q);
act = xchg(&f->action, act);
sch_tree_unlock(tp->q);
tcf_action_destroy(act,TCA_ACT_UNBIND);
}
if(tb[TCA_FW_ACT-1]) {
act = kmalloc(sizeof(*act),GFP_KERNEL);
if (NULL == act)
return -ENOMEM;
memset(act,0,sizeof(*act));
ret = tcf_action_init(tb[TCA_FW_ACT-1], tca[TCA_RATE-1],act,NULL, TCA_ACT_NOREPLACE,TCA_ACT_BIND);
if (0 > ret) {
tcf_action_destroy(act,TCA_ACT_UNBIND);
return ret;
}
sch_tree_lock(tp->q);
act = xchg(&f->action, act);
sch_tree_unlock(tp->q);
tcf_action_destroy(act,TCA_ACT_UNBIND);
}
#ifdef CONFIG_NET_CLS_IND
if(tb[TCA_FW_INDEV-1]) {
struct rtattr *idev = tb[TCA_FW_INDEV-1];
if (RTA_PAYLOAD(idev) >= IFNAMSIZ) {
printk("cls_fw: bad indev name %s\n",(char*)RTA_DATA(idev));
err = -EINVAL;
goto errout;
}
memset(f->indev,0,IFNAMSIZ);
sprintf(f->indev, "%s", (char*)RTA_DATA(idev));
}
#endif
#else /* only POLICE defined */
#ifdef CONFIG_NET_CLS_POLICE
if (tb[TCA_FW_POLICE-1]) {
struct tcf_police *police = tcf_police_locate(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1]);
tcf_tree_lock(tp);
police = xchg(&f->police, police);
tcf_tree_unlock(tp);
tcf_police_release(police,TCA_ACT_UNBIND);
}
#endif
#endif
return 0;
} }
if (!handle) if (!handle)
...@@ -336,45 +300,9 @@ static int fw_change(struct tcf_proto *tp, unsigned long base, ...@@ -336,45 +300,9 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
f->id = handle; f->id = handle;
if (tb[TCA_FW_CLASSID-1]) { err = fw_change_attrs(tp, f, tb, tca, base);
err = -EINVAL; if (err < 0)
if (RTA_PAYLOAD(tb[TCA_FW_CLASSID-1]) != 4) goto errout;
goto errout;
f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]);
cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
}
#ifdef CONFIG_NET_CLS_ACT
if(tb[TCA_FW_ACT-1]) {
act = kmalloc(sizeof(*act),GFP_KERNEL);
if (NULL == act)
return -ENOMEM;
memset(act,0,sizeof(*act));
ret = tcf_action_init(tb[TCA_FW_ACT-1], tca[TCA_RATE-1],act,NULL,TCA_ACT_NOREPLACE,TCA_ACT_BIND);
if (0 > ret) {
tcf_action_destroy(act,TCA_ACT_UNBIND);
return ret;
}
f->action= act;
}
#ifdef CONFIG_NET_CLS_IND
if(tb[TCA_FW_INDEV-1]) {
struct rtattr *idev = tb[TCA_FW_INDEV-1];
if (RTA_PAYLOAD(idev) >= IFNAMSIZ) {
printk("cls_fw: bad indev name %s\n",(char*)RTA_DATA(idev));
err = -EINVAL;
goto errout;
}
memset(f->indev,0,IFNAMSIZ);
sprintf(f->indev, "%s", (char*)RTA_DATA(idev));
}
#endif
#else
#ifdef CONFIG_NET_CLS_POLICE
if (tb[TCA_FW_POLICE-1])
f->police = tcf_police_locate(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1]);
#endif
#endif
f->next = head->ht[fw_hash(handle)]; f->next = head->ht[fw_hash(handle)];
tcf_tree_lock(tp); tcf_tree_lock(tp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment