cls_fw.c (f43dc23d5ea91fca257be02138a255f02d98e806) | cls_fw.c (cc7ec456f82da7f89a5b376e613b3ac4311b3e9a) |
---|---|
1/* 2 * net/sched/cls_fw.c Classifier mapping ipchains' fwmark to traffic class. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * --- 17 unchanged lines hidden (view full) --- 26#include <linux/errno.h> 27#include <linux/skbuff.h> 28#include <net/netlink.h> 29#include <net/act_api.h> 30#include <net/pkt_cls.h> 31 32#define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *)) 33 | 1/* 2 * net/sched/cls_fw.c Classifier mapping ipchains' fwmark to traffic class. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * --- 17 unchanged lines hidden (view full) --- 26#include <linux/errno.h> 27#include <linux/skbuff.h> 28#include <net/netlink.h> 29#include <net/act_api.h> 30#include <net/pkt_cls.h> 31 32#define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *)) 33 |
34struct fw_head 35{ | 34struct fw_head { |
36 struct fw_filter *ht[HTSIZE]; 37 u32 mask; 38}; 39 | 35 struct fw_filter *ht[HTSIZE]; 36 u32 mask; 37}; 38 |
40struct fw_filter 41{ | 39struct fw_filter { |
42 struct fw_filter *next; 43 u32 id; 44 struct tcf_result res; 45#ifdef CONFIG_NET_CLS_IND 46 char indev[IFNAMSIZ]; 47#endif /* CONFIG_NET_CLS_IND */ 48 struct tcf_exts exts; 49}; 50 51static const struct tcf_ext_map fw_ext_map = { 52 .action = TCA_FW_ACT, 53 .police = TCA_FW_POLICE 54}; 55 | 40 struct fw_filter *next; 41 u32 id; 42 struct tcf_result res; 43#ifdef CONFIG_NET_CLS_IND 44 char indev[IFNAMSIZ]; 45#endif /* CONFIG_NET_CLS_IND */ 46 struct tcf_exts exts; 47}; 48 49static const struct tcf_ext_map fw_ext_map = { 50 .action = TCA_FW_ACT, 51 .police = TCA_FW_POLICE 52}; 53 |
56static __inline__ int fw_hash(u32 handle) | 54static inline int fw_hash(u32 handle) |
57{ 58 if (HTSIZE == 4096) 59 return ((handle >> 24) & 0xFFF) ^ 60 ((handle >> 12) & 0xFFF) ^ 61 (handle & 0xFFF); 62 else if (HTSIZE == 2048) 63 return ((handle >> 22) & 0x7FF) ^ 64 ((handle >> 11) & 0x7FF) ^ --- 12 unchanged lines hidden (view full) --- 77 return t[0] ^ t[1] ^ t[2] ^ t[3]; 78 } else 79 return handle & (HTSIZE - 1); 80} 81 82static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, 83 struct tcf_result *res) 84{ | 55{ 56 if (HTSIZE == 4096) 57 return ((handle >> 24) & 0xFFF) ^ 58 ((handle >> 12) & 0xFFF) ^ 59 (handle & 0xFFF); 60 else if (HTSIZE == 2048) 61 return ((handle >> 22) & 0x7FF) ^ 62 ((handle >> 11) & 0x7FF) ^ --- 12 unchanged lines hidden (view full) --- 75 return t[0] ^ t[1] ^ t[2] ^ t[3]; 76 } else 77 return handle & (HTSIZE - 1); 78} 79 80static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, 81 struct tcf_result *res) 82{ |
85 struct fw_head *head = (struct fw_head*)tp->root; | 83 struct fw_head *head = (struct fw_head *)tp->root; |
86 struct fw_filter *f; 87 int r; 88 u32 id = skb->mark; 89 90 if (head != NULL) { 91 id &= head->mask; | 84 struct fw_filter *f; 85 int r; 86 u32 id = skb->mark; 87 88 if (head != NULL) { 89 id &= head->mask; |
92 for (f=head->ht[fw_hash(id)]; f; f=f->next) { | 90 for (f = head->ht[fw_hash(id)]; f; f = f->next) { |
93 if (f->id == id) { 94 *res = f->res; 95#ifdef CONFIG_NET_CLS_IND 96 if (!tcf_match_indev(skb, f->indev)) 97 continue; 98#endif /* CONFIG_NET_CLS_IND */ 99 r = tcf_exts_exec(skb, &f->exts, res); 100 if (r < 0) 101 continue; 102 103 return r; 104 } 105 } 106 } else { 107 /* old method */ | 91 if (f->id == id) { 92 *res = f->res; 93#ifdef CONFIG_NET_CLS_IND 94 if (!tcf_match_indev(skb, f->indev)) 95 continue; 96#endif /* CONFIG_NET_CLS_IND */ 97 r = tcf_exts_exec(skb, &f->exts, res); 98 if (r < 0) 99 continue; 100 101 return r; 102 } 103 } 104 } else { 105 /* old method */ |
108 if (id && (TC_H_MAJ(id) == 0 || !(TC_H_MAJ(id^tp->q->handle)))) { | 106 if (id && (TC_H_MAJ(id) == 0 || 107 !(TC_H_MAJ(id ^ tp->q->handle)))) { |
109 res->classid = id; 110 res->class = 0; 111 return 0; 112 } 113 } 114 115 return -1; 116} 117 118static unsigned long fw_get(struct tcf_proto *tp, u32 handle) 119{ | 108 res->classid = id; 109 res->class = 0; 110 return 0; 111 } 112 } 113 114 return -1; 115} 116 117static unsigned long fw_get(struct tcf_proto *tp, u32 handle) 118{ |
120 struct fw_head *head = (struct fw_head*)tp->root; | 119 struct fw_head *head = (struct fw_head *)tp->root; |
121 struct fw_filter *f; 122 123 if (head == NULL) 124 return 0; 125 | 120 struct fw_filter *f; 121 122 if (head == NULL) 123 return 0; 124 |
126 for (f=head->ht[fw_hash(handle)]; f; f=f->next) { | 125 for (f = head->ht[fw_hash(handle)]; f; f = f->next) { |
127 if (f->id == handle) 128 return (unsigned long)f; 129 } 130 return 0; 131} 132 133static void fw_put(struct tcf_proto *tp, unsigned long f) 134{ 135} 136 137static int fw_init(struct tcf_proto *tp) 138{ 139 return 0; 140} 141 | 126 if (f->id == handle) 127 return (unsigned long)f; 128 } 129 return 0; 130} 131 132static void fw_put(struct tcf_proto *tp, unsigned long f) 133{ 134} 135 136static int fw_init(struct tcf_proto *tp) 137{ 138 return 0; 139} 140 |
142static inline void 143fw_delete_filter(struct tcf_proto *tp, struct fw_filter *f) | 141static void fw_delete_filter(struct tcf_proto *tp, struct fw_filter *f) |
144{ 145 tcf_unbind_filter(tp, &f->res); 146 tcf_exts_destroy(tp, &f->exts); 147 kfree(f); 148} 149 150static void fw_destroy(struct tcf_proto *tp) 151{ 152 struct fw_head *head = tp->root; 153 struct fw_filter *f; 154 int h; 155 156 if (head == NULL) 157 return; 158 | 142{ 143 tcf_unbind_filter(tp, &f->res); 144 tcf_exts_destroy(tp, &f->exts); 145 kfree(f); 146} 147 148static void fw_destroy(struct tcf_proto *tp) 149{ 150 struct fw_head *head = tp->root; 151 struct fw_filter *f; 152 int h; 153 154 if (head == NULL) 155 return; 156 |
159 for (h=0; h<HTSIZE; h++) { 160 while ((f=head->ht[h]) != NULL) { | 157 for (h = 0; h < HTSIZE; h++) { 158 while ((f = head->ht[h]) != NULL) { |
161 head->ht[h] = f->next; 162 fw_delete_filter(tp, f); 163 } 164 } 165 kfree(head); 166} 167 168static int fw_delete(struct tcf_proto *tp, unsigned long arg) 169{ | 159 head->ht[h] = f->next; 160 fw_delete_filter(tp, f); 161 } 162 } 163 kfree(head); 164} 165 166static int fw_delete(struct tcf_proto *tp, unsigned long arg) 167{ |
170 struct fw_head *head = (struct fw_head*)tp->root; 171 struct fw_filter *f = (struct fw_filter*)arg; | 168 struct fw_head *head = (struct fw_head *)tp->root; 169 struct fw_filter *f = (struct fw_filter *)arg; |
172 struct fw_filter **fp; 173 174 if (head == NULL || f == NULL) 175 goto out; 176 | 170 struct fw_filter **fp; 171 172 if (head == NULL || f == NULL) 173 goto out; 174 |
177 for (fp=&head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) { | 175 for (fp = &head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) { |
178 if (*fp == f) { 179 tcf_tree_lock(tp); 180 *fp = f->next; 181 tcf_tree_unlock(tp); 182 fw_delete_filter(tp, f); 183 return 0; 184 } 185 } --- 49 unchanged lines hidden (view full) --- 235 return err; 236} 237 238static int fw_change(struct tcf_proto *tp, unsigned long base, 239 u32 handle, 240 struct nlattr **tca, 241 unsigned long *arg) 242{ | 176 if (*fp == f) { 177 tcf_tree_lock(tp); 178 *fp = f->next; 179 tcf_tree_unlock(tp); 180 fw_delete_filter(tp, f); 181 return 0; 182 } 183 } --- 49 unchanged lines hidden (view full) --- 233 return err; 234} 235 236static int fw_change(struct tcf_proto *tp, unsigned long base, 237 u32 handle, 238 struct nlattr **tca, 239 unsigned long *arg) 240{ |
243 struct fw_head *head = (struct fw_head*)tp->root; | 241 struct fw_head *head = (struct fw_head *)tp->root; |
244 struct fw_filter *f = (struct fw_filter *) *arg; 245 struct nlattr *opt = tca[TCA_OPTIONS]; 246 struct nlattr *tb[TCA_FW_MAX + 1]; 247 int err; 248 249 if (!opt) 250 return handle ? -EINVAL : 0; 251 --- 45 unchanged lines hidden (view full) --- 297 298errout: 299 kfree(f); 300 return err; 301} 302 303static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg) 304{ | 242 struct fw_filter *f = (struct fw_filter *) *arg; 243 struct nlattr *opt = tca[TCA_OPTIONS]; 244 struct nlattr *tb[TCA_FW_MAX + 1]; 245 int err; 246 247 if (!opt) 248 return handle ? -EINVAL : 0; 249 --- 45 unchanged lines hidden (view full) --- 295 296errout: 297 kfree(f); 298 return err; 299} 300 301static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg) 302{ |
305 struct fw_head *head = (struct fw_head*)tp->root; | 303 struct fw_head *head = (struct fw_head *)tp->root; |
306 int h; 307 308 if (head == NULL) 309 arg->stop = 1; 310 311 if (arg->stop) 312 return; 313 --- 13 unchanged lines hidden (view full) --- 327 } 328 } 329} 330 331static int fw_dump(struct tcf_proto *tp, unsigned long fh, 332 struct sk_buff *skb, struct tcmsg *t) 333{ 334 struct fw_head *head = (struct fw_head *)tp->root; | 304 int h; 305 306 if (head == NULL) 307 arg->stop = 1; 308 309 if (arg->stop) 310 return; 311 --- 13 unchanged lines hidden (view full) --- 325 } 326 } 327} 328 329static int fw_dump(struct tcf_proto *tp, unsigned long fh, 330 struct sk_buff *skb, struct tcmsg *t) 331{ 332 struct fw_head *head = (struct fw_head *)tp->root; |
335 struct fw_filter *f = (struct fw_filter*)fh; | 333 struct fw_filter *f = (struct fw_filter *)fh; |
336 unsigned char *b = skb_tail_pointer(skb); 337 struct nlattr *nest; 338 339 if (f == NULL) 340 return skb->len; 341 342 t->tcm_handle = f->id; 343 --- 58 unchanged lines hidden --- | 334 unsigned char *b = skb_tail_pointer(skb); 335 struct nlattr *nest; 336 337 if (f == NULL) 338 return skb->len; 339 340 t->tcm_handle = f->id; 341 --- 58 unchanged lines hidden --- |