Commit | Line | Data |
---|---|---|
db753079 JHS |
1 | /* |
2 | * include/net/act_generic.h | |
3 | * | |
4 | */ | |
1eda339e JHS |
5 | #ifndef _NET_ACT_GENERIC_H |
6 | #define _NET_ACT_GENERIC_H | |
db753079 JHS |
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 */ |