1#ifndef CLICK_FLOWNODES_HH
2#define CLICK_FLOWNODES_HH 1
4#include <click/allocator.hh>
7#include "../level/flow_level.hh"
9#define FLOW_NODE_DEFINE(T,fnt) \
10 static FlowNodePtr* find_ptr(void* thunk, FlowNodeData data, bool &need_grow) {\
11 return static_cast<T*>(thunk)->fnt(data,need_grow);\
36 typedef FlowNodePtr* (*FindFn)(
void*,FlowNodeData data,
bool &need_grow);
40#if FLOW_KEEP_STRUCTURE
44 void duplicate_internal(FlowNode* node,
bool recursive,
int use_count,
bool duplicate_leaf) {
46 if (unlikely(recursive)) {
47 this->_level = node->level()->duplicate();
49 if ( _default.is_node()) {
50 _default.set_node(node->_default.node->duplicate(recursive, use_count, duplicate_leaf));
52 _default.set_parent(
this);
55 _default.set_leaf(_default.leaf->duplicate(use_count));
56 _default.set_parent(
this);
58 _default.set_leaf(_default.leaf);
63 NodeIterator it = node->iterator();
65 while ((child = it.next()) != 0) {
66 if (child->is_leaf()) {
68 FlowControlBlock* new_leaf = child->leaf->duplicate(use_count);
69 new_leaf->parent =
this;
70 add_leaf(child->data(),new_leaf);
72 add_leaf(child->data(),child->leaf);
75 FlowNode* new_node = child->node->duplicate(recursive, use_count, duplicate_leaf);
76 new_node->set_parent(
this);
77 add_node(child->data(),new_node);
81 this->assert_diff(node);
90 inline bool _leaf_reverse_match(FlowControlBlock* &leaf,
Packet* &p) {
92 if (default_ptr()->ptr == leaf) {
93#if DEBUG_CLASSIFIER_MATCH > 1
94 click_chatter(
"%d -> %p %p",level()->get_data(p),this->find_or_default(level()->get_data(p))->ptr,leaf);
96 return this->find_or_default(level()->get_data(p))->ptr == leaf;
98 return level()->get_data(p).equals(leaf->get_data());
105 inline bool _node_reverse_match(FlowNode* &child,
Packet* &p) {
106 if (default_ptr()->ptr == child)
107 return this->find_or_default(level()->get_data(p))->ptr == child;
109 return level()->get_data(p).equals(child->node_data);
116 void assert_diff(FlowNode* node) {
117 assert(node->level() != this->level());
118 FlowNode::NodeIterator it = this->iterator();
119 FlowNode::NodeIterator ito = node->iterator();
122 while ((child = it.next()) != 0) {
124 assert(child != childo);
125 assert(child->is_leaf() == childo->is_leaf());
126 if (child->is_leaf()) {
128 child->node->assert_diff(childo->node);
131 assert(this->default_ptr() != node->default_ptr());
135 FlowNodeData node_data;
145 virtual void destroy() {
150 FlowNode() : num(0), _level(0), _default(), _parent(0), _growing(false), node_data()
151#if FLOW_KEEP_STRUCTURE
157 static FlowNode* create_hash(
int l);
158 FlowLevel* level()
const {
162 void set_level(FlowLevel* level) {
166 inline void add_node(FlowNodeData data, FlowNode* node) {
168 FlowNodePtr* ptr = _find(
this,data,need_grow);
170 click_chatter(
"FATAL ERROR : Adding node to an existing node");
173 flow_assert(ptr->ptr == 0);
180 inline void add_leaf(FlowNodeData data, FlowControlBlock* leaf) {
182 FlowNodePtr* ptr = _find(
this,data,need_grow);
183 flow_assert(ptr->ptr == 0);
192 void apply(std::function<
void(FlowNodePtr*)> fnt);
196 void apply_default(std::function<
void(FlowNodePtr*)> fnt);
198 FlowNode* combine(FlowNode* other,
bool as_child,
bool priority,
bool duplicate_leaf,
Element* origin) CLICK_WARN_UNUSED_RESULT;
199 void __combine_child(FlowNode* other,
bool priority,
bool duplicate_leaf,
Element* origin);
200 void __combine_else(FlowNode* other,
bool priority,
bool duplicate_leaf,
Element* origin);
201 FlowNodePtr prune(FlowLevel* level,FlowNodeData data,
bool inverted,
bool &changed) CLICK_WARN_UNUSED_RESULT;
203 FlowNode* find_node(FlowNode* other);
205 virtual FlowNode* duplicate(
bool recursive,
int use_count,
bool duplicate_leaf) = 0;
207 void assign(FlowNode* node) {
208 _level = node->_level;
209 _parent = node->_parent;
210 _default = node->_default;
213 int getNum()
const {
return num; };
218 virtual ~FlowNode() {
226#if FLOW_KEEP_STRUCTURE
227 inline bool released()
const {
231 inline void release() {
232 flow_assert(!growing());
235 apply([](FlowNodePtr* p) {
236 if (p->ptr && p->is_node()) {
237#if FLOW_KEEP_STRUCTURE
238 flow_assert(p->node->released());
247 inline FlowNodePtr* find(FlowNodeData data,
bool &need_grow) {
248 return _find((
void*)
this,data,need_grow);
252 inline FlowNodePtr* find_or_default(
const FlowNodeData data) {
254 FlowNodePtr* ptr = _find(
this,data,need_grow);
256#
if FLOW_KEEP_STRUCTURE
257 || (ptr->is_node() && ptr->node->released())
260 return default_ptr();
272 inline FlowNode* parent()
const {
276 inline FlowNodePtr get_default() {
280 inline FlowNodePtr* default_ptr() {
285 inline void set_default(FlowNodePtr ptr) {
287 flow_assert(ptr.ptr !=
this);
289 _default.set_parent(
this);
291 flow_assert(_default.ptr == ptr.ptr);
295 inline void set_default(FlowNode* node) {
296 flow_assert(_default.ptr == 0);
297 flow_assert(node !=
this);
299 node->set_parent(
this);
302 virtual void release_child(FlowNodePtr fl, FlowNodeData data) = 0;
304#if FLOW_KEEP_STRUCTURE
305 inline void renew() {
310 virtual String name()
const = 0;
312 class NodeIteratorBase {
314 virtual ~NodeIteratorBase() =
default;
315 virtual FlowNodePtr* next() = 0;
320 NodeIteratorBase* _base;
322 NodeIterator(NodeIteratorBase* b) {
328 FlowNodePtr* next() {
329 return _base->next();
331 NodeIterator operator=(
const NodeIterator& it) {
332 NodeIterator nit(it._base);
339 FlowNode* p = _parent;
340 while (p->parent() != 0) {
345 virtual NodeIterator iterator() = 0;
347 inline void set_parent(FlowNode* parent) {
352 bool growing()
const {
356 void set_growing(
bool g) {
360 FlowNode* start_growing(
bool impl);
362#if DEBUG_CLASSIFIER || DEBUG_CLASSIFIER_CHECK
363 void check(
bool allow_parent =
false,
bool allow_default=
true,
bool multithread=
false);
365 inline void check(
bool allow_parent =
false,
bool allow_default=
true) {};
368 virtual FlowNode* optimize(
Bitvector threads) CLICK_WARN_UNUSED_RESULT;
370 void traverse_all_leaves(std::function<
void(FlowNodePtr*)> fnt,
bool do_final,
bool do_default);
372 void traverse_all_leaves_and_empty_default(std::function<
void(FlowNodePtr*,FlowNode*)> fnt,
bool do_final,
bool do_default);
374 bool traverse_all_default_leaf(std::function<
bool(FlowNode*)> fnt);
376 bool traverse_all_nodes(std::function<
bool(FlowNode*)> fnt);
378 void traverse_parents(std::function<
bool(FlowNode*)> fnt);
380 void traverse_parents(std::function<
void(FlowNode*)> fnt);
384 bool is_full_dummy();
386 bool has_no_default(
bool allow_dynamic =
false);
388 void reverse_print();
389 static void print(
const FlowNode* node,
String prefix,
int data_offset = -1,
bool show_ptr =
true,
bool recursive=
true,
bool do_release =
true);
392 inline void print(
int data_offset = -1,
bool show_ptr =
true,
bool recursive =
true,
bool do_release =
true)
const {
393#if DEBUG_CLASSIFIER > 2
396 click_chatter(
"---");
397 print(
this,
"", data_offset, show_ptr, recursive, do_release);
398 click_chatter(
"---");
399#if DEBUG_CLASSIFIER > 2
404 void debug_print(
int data_offset = -1)
const {
405 print(data_offset,
true);
408 void debug_print(
int = -1)
const {}
411 void leaf_combine_data(FlowControlBlock* leaf,
bool do_final,
bool do_default,
Element* origin);
412 void leaf_combine_data_create(FlowControlBlock* leaf,
bool do_final,
bool do_default,
bool discard_my_data,
Element* origin);
413 FlowNodePtr prune(FlowNode* parent, FlowNodeData data);
414 FlowNodePtr prune_with_parent(FlowNode* parent, FlowNodeData data,
bool was_default);
415 FlowNode* replace_leaves(FlowNode* other,
bool do_final,
bool do_default,
bool discard_my_fcb_data,
Element* origin);
416 friend class FlowClassificationTable;
417 friend class FlowNodePtr;
420template <
typename T,
int POOL_SIZE,
int POOL_COUNT>
421 friend class pool_allocator_aware_mt;