This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / include / net / act_generic.h
1 /*
2  * include/net/act_generic.h
3  *
4 */
5 #ifndef _NET_ACT_GENERIC_H
6 #define _NET_ACT_GENERIC_H
7 static inline int tcf_defact_release(struct tcf_defact *p, int bind)
8 {
9         int ret = 0;
10         if (p) {
11                 if (bind) {
12                         p->bindcnt--;
13                 }
14                 p->refcnt--;
15                 if (p->bindcnt <= 0 && p->refcnt <= 0) {
16                         kfree(p->defdata);
17                         tcf_hash_destroy(p);
18                         ret = 1;
19                 }
20         }
21         return ret;
22 }
23
24 static inline int
25 alloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
26 {
27         p->defdata = kmalloc(datalen, GFP_KERNEL);
28         if (p->defdata == NULL)
29                 return -ENOMEM;
30         p->datalen = datalen;
31         memcpy(p->defdata, defdata, datalen);
32         return 0;
33 }
34
35 static inline int
36 realloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
37 {
38         /* safer to be just brute force for now */
39         kfree(p->defdata);
40         return alloc_defdata(p, datalen, defdata);
41 }
42
43 static inline int
44 tcf_defact_init(struct rtattr *rta, struct rtattr *est,
45                 struct tc_action *a, int ovr, int bind)
46 {
47         struct rtattr *tb[TCA_DEF_MAX];
48         struct tc_defact *parm;
49         struct tcf_defact *p;
50         void *defdata;
51         u32 datalen = 0;
52         int ret = 0;
53
54         if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)
55                 return -EINVAL;
56
57         if (tb[TCA_DEF_PARMS - 1] == NULL || 
58             RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm))
59                 return -EINVAL;
60
61         parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);
62         defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]);
63         if (defdata == NULL)
64                 return -EINVAL;
65
66         datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]);
67         if (datalen <= 0)
68                 return -EINVAL;
69
70         p = tcf_hash_check(parm->index, a, ovr, bind);
71         if (p == NULL) {
72                 p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
73                 if (p == NULL)
74                         return -ENOMEM;
75
76                 ret = alloc_defdata(p, datalen, defdata);
77                 if (ret < 0) {
78                         kfree(p);
79                         return ret;
80                 }
81                 ret = ACT_P_CREATED;
82         } else {
83                 if (!ovr) {
84                         tcf_defact_release(p, bind);
85                         return -EEXIST;
86                 }
87                 realloc_defdata(p, datalen, defdata);
88         }
89
90         spin_lock_bh(&p->lock);
91         p->action = parm->action;
92         spin_unlock_bh(&p->lock);
93         if (ret == ACT_P_CREATED)
94                 tcf_hash_insert(p);
95         return ret;
96 }
97
98 static inline int tcf_defact_cleanup(struct tc_action *a, int bind)
99 {
100         struct tcf_defact *p = PRIV(a, defact);
101
102         if (p != NULL)
103                 return tcf_defact_release(p, bind);
104         return 0;
105 }
106
107 static inline int
108 tcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
109 {
110         unsigned char *b = skb->tail;
111         struct tc_defact opt;
112         struct tcf_defact *p = PRIV(a, defact);
113         struct tcf_t t;
114
115         opt.index = p->index;
116         opt.refcnt = p->refcnt - ref;
117         opt.bindcnt = p->bindcnt - bind;
118         opt.action = p->action;
119         RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
120         RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata);
121         t.install = jiffies_to_clock_t(jiffies - p->tm.install);
122         t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
123         t.expires = jiffies_to_clock_t(p->tm.expires);
124         RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);
125         return skb->len;
126
127 rtattr_failure:
128         skb_trim(skb, b - skb->data);
129         return -1;
130 }
131
132 #define tca_use_default_ops \
133         .dump           =       tcf_defact_dump, \
134         .cleanup        =       tcf_defact_cleanup, \
135         .init           =       tcf_defact_init, \
136         .walk           =       tcf_generic_walker, \
137
138 #define tca_use_default_defines(name) \
139         static u32 idx_gen; \
140         static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \
141         static DEFINE_RWLOCK(##name_lock);
142 #endif /* _NET_ACT_GENERIC_H */