* Changes:
*
* Eduardo J. Blanco <ejbs@netlabs.com.uy> :990222: kmod support
+ *
*/
#include <asm/uaccess.h>
#include <net/sock.h>
#include <net/pkt_sched.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;
struct tcf_proto_ops *tp_ops;
struct Qdisc_class_ops *cops;
unsigned long cl = 0;
- unsigned long fh;
+ unsigned long fh, fh_s;
int err;
if (prio == 0) {
kfree(tp);
goto errout;
}
- write_lock(&qdisc_tree_lock);
- spin_lock_bh(&dev->queue_lock);
+
+ qdisc_lock_tree(dev);
tp->next = *back;
*back = tp;
- spin_unlock_bh(&dev->queue_lock);
- write_unlock(&qdisc_tree_lock);
+ qdisc_unlock_tree(dev);
+
} else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
goto errout;
- fh = tp->ops->get(tp, t->tcm_handle);
+ fh_s = fh = tp->ops->get(tp, t->tcm_handle);
if (fh == 0) {
if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
- write_lock(&qdisc_tree_lock);
- spin_lock_bh(&dev->queue_lock);
+ qdisc_lock_tree(dev);
*back = tp->next;
- spin_unlock_bh(&dev->queue_lock);
- write_unlock(&qdisc_tree_lock);
+ qdisc_unlock_tree(dev);
+
+ tfilter_notify(skb, n, tp, fh_s, RTM_DELTFILTER);
tcf_destroy(tp);
err = 0;
goto errout;
break;
case RTM_DELTFILTER:
err = tp->ops->delete(tp, fh);
+ if (err == 0)
+ tfilter_notify(skb, n, tp, fh_s, RTM_DELTFILTER);
goto errout;
case RTM_GETTFILTER:
err = tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER);
return err;
}
+unsigned long tcf_set_class(struct tcf_proto *tp, unsigned long *clp,
+ unsigned long cl)
+{
+ unsigned long old_cl;
+
+ tcf_tree_lock(tp);
+ old_cl = __cls_set_class(clp, cl);
+ tcf_tree_unlock(tp);
+
+ return old_cl;
+}
+
+
static int
tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh,
u32 pid, u32 seq, unsigned flags, int event)
tcm->tcm_family = AF_UNSPEC;
tcm->tcm_ifindex = tp->q->dev->ifindex;
tcm->tcm_parent = tp->classid;
- tcm->tcm_handle = 0;
tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
RTA_PUT(skb, TCA_KIND, IFNAMSIZ, tp->ops->kind);
- if (tp->ops->dump && tp->ops->dump(tp, fh, skb, tcm) < 0)
- goto rtattr_failure;
+ 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;
+ }
nlh->nlmsg_len = skb->tail - b;
return skb->len;
if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL)
return skb->len;
- read_lock(&qdisc_tree_lock);
+ read_lock_bh(&qdisc_tree_lock);
if (!tcm->tcm_parent)
q = dev->qdisc_sleeping;
else
if (cl)
cops->put(q, cl);
out:
- read_unlock(&qdisc_tree_lock);
+ read_unlock_bh(&qdisc_tree_lock);
dev_put(dev);
return skb->len;
}
EXPORT_SYMBOL(register_tcf_proto_ops);
EXPORT_SYMBOL(unregister_tcf_proto_ops);
+EXPORT_SYMBOL(tcf_set_class);