Click
Loading...
Searching...
No Matches
flow_level.hh
1#ifndef CLICK_FLOWLEVEL_HH
2#define CLICK_FLOWLEVEL_HH 1
3#include <click/packet.hh>
4#if HAVE_DPDK
5#include <rte_flow.h>
6#endif
7#include "../common.hh"
8
9#define FLOW_LEVEL_DEFINE(T,fnt) \
10 static FlowNodeData get_data_ptr(void* thunk, Packet* p) {\
11 return static_cast<T*>(thunk)->fnt(p);\
12 }
13
14class FlowNode;
15
16class FlowNodePtr {
17private:
18 bool _is_leaf;
19public :
20 union {
21 FlowNode* node;
22 FlowControlBlock* leaf;
23 void* ptr;
24 };
25
26 FlowNodePtr() : _is_leaf(false), ptr(0) {
27
28 }
29
30 FlowNodePtr(FlowNode* n) : _is_leaf(false), node(n) {
31
32 }
33
34 FlowNodePtr(FlowControlBlock* sfcb) : _is_leaf(true), leaf(sfcb) {
35
36 }
37
38 inline FlowNodeData data();
39
40 inline FlowNode* parent() const;
41
42 inline void set_data(FlowNodeData data);
43
44 inline void set_parent(FlowNode* parent);
45
46 inline void set_leaf(FlowControlBlock* l) {
47 leaf = l;
48 _is_leaf = true;
49 }
50
51 inline void set_node(FlowNode* n) {
52 node = n;
53 _is_leaf = false;
54 }
55
56
57 inline bool is_leaf() const {
58 return _is_leaf;
59 }
60
61 inline bool is_node() const {
62 return !_is_leaf;
63 }
64
65 /* inline FlowNodePtr duplicate() {
66 FlowNodePtr v;
67 v.ptr = ptr;
68 v._is_leaf = _is_leaf;
69 v.set_data(data());
70 return v;
71 }
72 */
73 void print(int data_offset = -1) const;
74
75 //---
76 //Compile time functions
77 //---
78
79 FlowNodePtr optimize(Bitvector threads);
80
81 bool else_drop();
82
83 inline void traverse_all_leaves(std::function<void(FlowNodePtr*)>);
84
85 inline void check();
86
87 bool replace_leaf_with_node(FlowNode*, bool discard, Element* origin);
88
89 void node_combine_ptr(FlowNode* parent, FlowNodePtr, bool as_child, bool priority, bool no_dynamic, Element* origin);
90 void default_combine(FlowNode* parent, FlowNodePtr*, bool as_child, bool priority, Element* origin);
91};
92
93
94
95class FlowLevel {
96private:
97 //bool deletable;
98protected:
99 bool _dynamic;
100#if HAVE_LONG_CLASSIFICATION
101 bool _islong = false;
102#endif
103public:
104 FlowLevel() :
105 //deletable(true),
106 _dynamic(false) {
107
108 };
109
110 typedef FlowNodeData (*GetDataFn)(void*, Packet* packet);
111 GetDataFn _get_data;
112
113 virtual ~FlowLevel() {};
114
120 virtual long unsigned get_max_value() = 0;
121
122 virtual void add_offset(int offset) {};
123
124 virtual bool is_mt_safe() const { return false;};
125
126 virtual bool is_usefull() {
127 return true;
128 }
135 virtual bool prune(FlowLevel*) {return false;};
136
137 virtual FlowNodePtr prune(FlowLevel* other, FlowNodeData data, FlowNode* node, bool &changed);
138
144 virtual bool equals(FlowLevel* level) {
145 return typeid(*this) == typeid(*level) &&
146#if HAVE_LONG_CLASSIFICATION
147 _islong == level->_islong &&
148#endif
149 _dynamic == level->_dynamic;
150 }
151
152 inline FlowNodeData get_data(Packet* p) {
153 flow_assert(_get_data);
154 flow_assert(this);
155 return _get_data(this,p);
156 }
157
158 int current_level = 0;
159
160 FlowNode* create_node(FlowNode* parent, bool better, bool better_impl);
161
162 bool is_dynamic() {
163 return _dynamic;
164 }
165
166 void set_dynamic() {
167 _dynamic = true;
168 }
169
170 /*bool is_deletable() {
171 return deletable;
172 }*/
173
174 virtual String print() = 0;
175#if HAVE_LONG_CLASSIFICATION
176 inline bool is_long() const {
177 return _islong;
178 }
179#else
180 inline bool is_long() const {
181 return false;
182 }
183#endif
184 FlowLevel* assign(FlowLevel* l) {
185 _dynamic = l->_dynamic;
186 //deletable = l->deletable;
187#if HAVE_LONG_CLASSIFICATION
188 _islong = l->_islong;
189#endif
190 return this;
191 }
192
193 virtual FlowLevel *duplicate() = 0;
194
195 virtual FlowLevel *optimize(FlowNode*) {
196 return this;
197 }
198
199#if HAVE_DPDK
200 virtual int to_dpdk_flow(FlowNodeData data, rte_flow_item_type last_layer, int offset, rte_flow_item_type &next_layer, int &next_layer_offset, Vector<rte_flow_item> &pattern, bool is_default) {
201 return -1;
202 }
203#endif
204
205};
206
207
211class FlowLevelDummy : public FlowLevel {
212public:
213
215 _get_data = &get_data_ptr;
216 }
217 FLOW_LEVEL_DEFINE(FlowLevelDummy,get_data_dummy);
218
219 inline long unsigned get_max_value() {
220 return 0;
221 }
222
223 inline FlowNodeData get_data_dummy(Packet* packet) {
224/* click_chatter("FlowLevelDummy should be stripped !");
225 abort();*/
226 return FlowNodeData();
227 }
228
229 String print() {
230 return String("ANY");
231 }
232
233 FlowLevel* duplicate() override {
234 return (new FlowLevelDummy())->assign(this);
235 }
236
237#if HAVE_DPDK
238 virtual int to_dpdk_flow(FlowNodeData data, rte_flow_item_type last_layer, int offset, rte_flow_item_type &next_layer, int &next_layer_offset, Vector<rte_flow_item> &pattern, bool is_default) override {
239 rte_flow_item pat;
240 pat.type = RTE_FLOW_ITEM_TYPE_VOID;
241 next_layer = last_layer;
242 next_layer_offset = offset;
243 pattern.push_back(pat);
244 return 1;
245 }
246#endif
247
248};
249
253class FlowLevelAggregate : public FlowLevel {
254public:
255
256 FlowLevelAggregate(int offset, uint32_t mask) : offset(offset), mask(mask) {
257 _get_data = &get_data_ptr;
258 }
259
261 _get_data = &get_data_ptr;
262 }
263 FLOW_LEVEL_DEFINE(FlowLevelAggregate,get_data_agg);
264
265
266 int offset;
267 uint32_t mask;
268
269 inline long unsigned get_max_value() {
270 return mask;
271 }
272
273 inline FlowNodeData get_data_agg(Packet* packet) {
274 FlowNodeData data;
275 data.data_32 = (AGGREGATE_ANNO(packet) >> offset) & mask;
276 return data;
277 }
278
279 String print() {
280 return String("AGG");
281 }
282
283 FlowLevel* duplicate() override {
284 return (new FlowLevelAggregate(0,-1))->assign(this);
285 }
286};
287
291class FlowLevelThread : public FlowLevel {
292 int _numthreads;
293
294public:
295 FlowLevelThread(int nthreads) : _numthreads(nthreads) {
296 _get_data = &get_data_ptr;
297 }
298 FLOW_LEVEL_DEFINE(FlowLevelThread,get_data_thread);
299
300 virtual bool is_mt_safe() const override { return true;};
301 inline long unsigned get_max_value() {
302 return _numthreads - 1;
303 }
304
305 inline FlowNodeData get_data_thread(Packet*) {
306 return FlowNodeData((uint32_t)click_current_cpu_id());
307 }
308
309 String print() {
310 return String("THREAD");
311 }
312
313 FlowLevel* duplicate() override {
314 return (new FlowLevelThread(_numthreads))->assign(this);
315 }
316};
317
318class FlowLevelOffset : public FlowLevel {
319protected:
320 int _offset;
321
322public:
323
324 FlowLevelOffset(int offset) : _offset(offset) {
325
326 }
327 FlowLevelOffset() : FlowLevelOffset(0) {
328 }
329
330
331 void add_offset(int offset) {
332 _offset += offset;
333 }
334
335 int offset() const {
336 return _offset;
337 }
338
339 virtual int mask_size() const = 0;
340
341 virtual uint8_t get_mask(int o) const = 0;
342
343 bool equals(FlowLevel* level) {
344 return ((FlowLevel::equals(level))&& (_offset == dynamic_cast<FlowLevelOffset*>(level)->_offset));
345 }
346
347#if HAVE_DPDK
348 virtual int to_dpdk_flow(FlowNodeData data, rte_flow_item_type last_layer, int offset, rte_flow_item_type &next_layer, int &next_layer_offset, Vector<rte_flow_item> &pattern, bool is_default) override;
349#endif
350};
351
352static const char hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','F'};
353
357template <typename T>
358class FlowLevelGeneric : public FlowLevelOffset {
359private:
360 T _mask;
361public:
362
363 FlowLevelGeneric(T mask, int offset) : FlowLevelOffset(offset), _mask(mask) {
364 _get_data = &get_data_ptr;
365 }
366 FLOW_LEVEL_DEFINE(FlowLevelGeneric<T>,get_data);
367
369
370 }
371 void set_match(int offset, T mask) {
372 _mask = mask;
373 _offset = offset;
374 }
375
376 T mask() const {
377 return _mask;
378 }
379
380 virtual int mask_size() const {
381 return sizeof(T);
382 }
383
384 virtual uint8_t get_mask(int o) const override {
385 if (o < _offset) //2 < 0
386 return 0;
387 if (o >= _offset + mask_size())
388 return 0;
389 return ((uint8_t*)&_mask)[o-_offset];
390 }
391
392 virtual bool is_usefull() override {
393 return _mask != 0;
394 }
395
396 //Remove from the mask what is already set in other
397 virtual bool prune(FlowLevel* other) override;
398
402 virtual FlowNodePtr prune(FlowLevel* other, FlowNodeData data, FlowNode* node, bool &changed) override;
403
404 inline long unsigned get_max_value() {
405 return _mask;
406 }
407
408 inline FlowNodeData get_data(Packet* packet) {
409 return FlowNodeData((T)(*((T*)(packet->data() + _offset)) & _mask));
410 }
411
412 String print();
413
414 FlowLevel* duplicate() override {
415 return (new FlowLevelGeneric<T>(_mask,_offset))->assign(this);
416 }
417
418 bool equals(FlowLevel* level) {
419 return ((FlowLevelOffset::equals(level)) && (_mask == dynamic_cast<FlowLevelGeneric<T>*>(level)->_mask));
420 }
421
422
423 virtual FlowLevel *optimize(FlowNode* parent) override;
424};
425
429template <typename T>
430class FlowLevelField : public FlowLevelOffset {
431public:
432
433 FlowLevelField(int offset) : FlowLevelOffset(offset) {
434 _get_data = &get_data_ptr;
435 }
436 FLOW_LEVEL_DEFINE(FlowLevelField<T>,get_data);
437
439
440 }
441
442 T mask() const {
443 return (T)-1;
444 }
445
446 virtual uint8_t get_mask(int o) const {
447 if (o < _offset)
448 return 0;
449 if (o >= _offset + mask_size())
450 return 0;
451 return 0xff;
452 }
453
454 virtual int mask_size() const {
455 return sizeof(T);
456 }
457
458 inline long unsigned get_max_value() {
459 return mask();
460 }
461
462 inline FlowNodeData get_data(Packet* packet) {
463 //click_chatter("FlowLevelField %d %x, sz %d",_offset,*(T*)(packet->data() + _offset),sizeof(T));
464 return FlowNodeData(*(T*)(packet->data() + _offset));
465 }
466
467 String print() {
468 StringAccum s;
469 s << _offset;
470 s << "/";
471 for (int i = 0; i < sizeof(T); i++) {
472 s << "FF";
473 }
474 return s.take_string();
475 }
476
477 FlowLevel* duplicate() override {
478 return (new FlowLevelField<T>(_offset))->assign(this);
479 }
480
481};
482
483using FlowLevelGeneric8 = FlowLevelGeneric<uint8_t>;
484using FlowLevelGeneric16 = FlowLevelGeneric<uint16_t>;
485using FlowLevelGeneric32 = FlowLevelGeneric<uint32_t>;
486#if HAVE_LONG_CLASSIFICATION
487using FlowLevelGeneric64 = FlowLevelGeneric<uint64_t>;
488#endif
489using FlowLevelField8 = FlowLevelField<uint8_t>;
490using FlowLevelField16 = FlowLevelField<uint16_t>;
491using FlowLevelField32 = FlowLevelField<uint32_t>;
492#if HAVE_LONG_CLASSIFICATION
493using FlowLevelField64 = FlowLevelField<uint64_t>;
494#endif
495
496#endif
Vector of bits.
Definition bitvector.hh:21
Base class for Click elements.
Definition element.hh:42
Definition flow_level.hh:253
Definition flow_level.hh:211
Definition flow_level.hh:430
Definition flow_level.hh:358
virtual bool prune(FlowLevel *other) override
Definition flownode.cc:1085
Definition flow_level.hh:291
A network packet.
Definition packet.hh:68
const unsigned char * data() const
Return the packet's data pointer.
Definition packet.hh:1207
Efficiently build up Strings from pieces.
Definition straccum.hh:28
String take_string()
Return a String object with this StringAccum's contents.
Definition straccum.cc:211
A string of characters.
Definition string.hh:22
Vector template.
Definition vector.hh:111
void push_back(value_argument_type v)
Append element v.
Definition vector.hh:399
The Packet class models packets in Click.