8#include <click/multithread.hh>
12#include <click/allocator.hh>
21#include "node/flow_nodes.hh"
23inline void check_thread(FlowNode* parent, FlowNode* child) {
27 FlowNodeData data = child->node_data;
28 while (parent &&
dynamic_cast<FlowLevelThread*
>(parent->level()) == 0) {
30 data = child->node_data;
31 parent = parent->parent();
40 if (data.data_32 != click_current_cpu_id()) {
41 click_chatter(
"Thead %d in level of thread %d", click_current_cpu_id(), data.data_32);
47class FlowClassificationTable :
public FlowTableHolder {
49 FlowClassificationTable();
50 ~FlowClassificationTable();
52 void set_root(FlowNode* node);
55 inline FlowControlBlock* match(
Packet* p, FlowNode* parent);
57 inline FlowControlBlock* match(
Packet* p) {
58 return match(p, _root);
60 inline bool reverse_match(FlowControlBlock* sfcb,
Packet* p, FlowNode* root);
67 static Rule parse(
Element* owner,
String s,
bool verbose =
false,
bool add_leaf=
true);
68 static Rule make_drop_rule(
bool ed =
false) {
69 Rule r = parse(0,
"- drop");
71 r.root->traverse_all_leaves([](FlowNodePtr* ptr){ ptr->leaf->set_early_drop();},
true,
true);
87bool FlowClassificationTable::reverse_match(FlowControlBlock* sfcb,
Packet* p, FlowNode* root) {
88#if HAVE_FLOW_EXACT_MATCH
90 __m256i pdata = _mm256_loadu_si256((__m128i*) p->
data());
91 __m256i cdata = _mm256_loadu_si256((__m128i*) sfcb->val);
92 __m256i mask = _mm256_loadu_si256((__m128i*) *sfcb->mask);
93 pdata = _mm256_and_si256(pdata, mask);
94 cdata = _mm256_and_si256(cdata, mask);
95 return _mm256_testc_si256(pdata, cdata);
98 FlowNode* parent = (FlowNode*)sfcb->parent;
100 if (parent != root && (!parent || !root->find_node(parent))) {
101 click_chatter(
"GOING TO CRASH WHILE MATCHING fcb %p, with parent %p", sfcb, parent);
102 click_chatter(
"Parent exists : %d",root->find_node(parent));
104 sfcb->reverse_print();
108 if (unlikely(!parent->_leaf_reverse_match(sfcb,p))) {
109#if DEBUG_CLASSIFIER_MATCH > 2
110 click_chatter(
"DIF is_default %d Leaf %x %x level %s",parent->default_ptr()->ptr == sfcb,parent->level()->get_data(p).get_long(), sfcb->node_data[0].get_long(),parent->level()->print().c_str());
114#if DEBUG_CLASSIFIER_MATCH > 2
115 click_chatter(
"MAT is_default %d Leaf %x %x level %s",parent->default_ptr()->ptr == sfcb,parent->level()->get_data(p).get_long(), sfcb->node_data[0].get_long(),parent->level()->print().c_str());
119 while (parent != root) {
122 if (parent->threads.size() <= click_current_cpu_id() || !parent->threads[click_current_cpu_id()]) {
123 click_chatter(
"[%d] FATAL : Parent should not have this thread",click_current_cpu_id());
124 click_chatter(
"[%d] FATAL : Thread of parent : %s",click_current_cpu_id(),parent->threads.unparse().c_str());
126 assert(parent->threads[click_current_cpu_id()]);
129 FlowNode* child = parent;
130 parent = parent->parent();
132 flow_assert(child != parent);
135 if (child->level() == parent->level())
138 if (unlikely(!parent->_node_reverse_match(child,p))) {
139#if DEBUG_CLASSIFIER_MATCH > 2
140 click_chatter(
"DIF is_default %d Child %x %x level %s",parent->default_ptr()->ptr == child ,parent->level()->get_data(p).get_long(), child->node_data.get_long(),parent->level()->print().c_str());
144#if DEBUG_CLASSIFIER_MATCH > 2
145 click_chatter(
"MAT is_default %d Child %x %x level %s",parent->default_ptr()->ptr == child,parent->level()->get_data(p).get_long(), child->node_data.get_long(),parent->level()->print().c_str());
153FlowControlBlock* FlowClassificationTable::match(
Packet* p, FlowNode* parent) {
154 FlowNodePtr* child_ptr = 0;
157 FlowNode* debug_save_root = parent;
162 bool need_grow =
false;
163 FlowNodeData data = parent->level()->get_data(p);
164 debug_flow(
"[%d] Data level %d is %016llX %s",click_current_cpu_id(), level_nr++,data.get_long(),parent->level()->print().c_str());
165 child_ptr = parent->find(data,need_grow);
166 debug_flow(
"[%d] ->Ptr is %p, is_leaf : %d",click_current_cpu_id(), child_ptr->ptr, child_ptr->is_leaf());
167 if (unlikely(IS_FREE_PTR_ANY(child_ptr->ptr)
168#
if FLOW_KEEP_STRUCTURE
169 || (child_ptr->is_node() && child_ptr->node->released())
173 if (parent->get_default().ptr) {
175 if (parent->level()->is_dynamic()) {
176 if (unlikely(parent->growing())) {
192 flow_assert(parent->default_ptr()->node->parent() == parent);
193 parent = parent->default_ptr()->node;
197#if HAVE_STATIC_CLASSIFICATION
198 click_chatter(
"MAX CAPACITY ACHIEVED, DROPPING");
201 parent = parent->start_growing(
false);
203 click_chatter(
"Could not grow !? Dropping flow !");
207 flow_assert(_root->find_node(parent));
212#if DEBUG_CLASSIFIER_CHECK
213 if(parent->getNum() != parent->findGetNum()) {
214 click_chatter(
"%d %d",parent->getNum(), parent->findGetNum());
217 flow_assert(parent->getNum() < parent->max_size());
220 if (parent->get_default().is_leaf()) {
221 debug_flow(
"[%d] DUPLICATE leaf %p", click_current_cpu_id(),parent->get_default().ptr);
224 child_ptr->set_leaf(_pool.allocate());
225 flow_assert(child_ptr->leaf);
226 flow_assert(child_ptr->is_leaf());
227 child_ptr->leaf->initialize();
228 child_ptr->leaf->parent = parent;
233 child_ptr->set_data(data);
234 memcpy(&child_ptr->leaf->node_data[1], &parent->default_ptr()->leaf->node_data[1] ,_pool.data_size() -
sizeof(FlowNodeData));
235 #if DEBUG_CLASSIFIER_MATCH > 3
238 _root->check(
true,
false);
240 if (parent->threads.weight() == 1)
241 child_ptr->leaf->thread = parent->threads.clz();
243 child_ptr->leaf->thread = -1;
244 flow_assert(child_ptr->leaf->thread == -1 || child_ptr->leaf->thread == click_current_cpu_id());
246 flow_assert(reverse_match(child_ptr->leaf, p, debug_save_root));
247 return child_ptr->leaf;
249#if FLOW_KEEP_STRUCTURE
250 if (child_ptr->ptr && child_ptr->node->released()) {
251 child_ptr->node->renew();
252 child_ptr->set_data(data);
258 FlowNode* defNode = parent->default_ptr()->node;
259 flow_assert(parent->default_ptr()->node->getNum() == 0);
260 FlowNode* newNode = defNode->level()->create_node(defNode,
false,
false);
261 newNode->_level = defNode->level();
262 *newNode->default_ptr() = *defNode->default_ptr();
263 child_ptr->set_node(newNode);
264 debug_flow(
"[%d] DUPLICATE node, new is %p, default is %p",click_current_cpu_id(),child_ptr->node,parent->default_ptr()->ptr);
266 child_ptr->set_data(data);
267 child_ptr->set_parent(parent);
269 newNode->threads.clear();
270 newNode->threads.resize(click_max_cpu_ids());
271 newNode->threads[click_current_cpu_id()] =
true;
272 flow_assert(parent->threads[click_current_cpu_id()]);
277 flow_assert(parent->getNum() == parent->findGetNum());
279 _root->check(
true,
false);
284 flow_assert(child_ptr->node->threads[click_current_cpu_id()]);
285 child_ptr = parent->default_ptr();
286 if (child_ptr->is_leaf()) {
287 _root->check(
true,
false);
288 flow_assert(reverse_match(child_ptr->leaf, p, debug_save_root));
289 return child_ptr->leaf;
293 click_chatter(
"ERROR : no classification node and no default path !");
294 click_chatter(
"Level %s, data %lu", parent->level()->print().c_str(),data.get_long());
298 }
else if (child_ptr->is_leaf()) {
299 flow_assert(child_ptr->leaf->thread == -1 || child_ptr->leaf->thread == click_current_cpu_id());
301 if (child_ptr->leaf->parent()) {
302 flow_assert(reverse_match(child_ptr->leaf, p));
305 return child_ptr->leaf;
308 flow_assert(child_ptr->node->threads[click_current_cpu_id()]);
311 flow_assert(child_ptr->node->parent() == parent);
312 parent = child_ptr->node;
318inline FlowNodeData FlowNodePtr::data() {
320 return leaf->node_data[0];
322 return node->node_data;
325inline FlowNode* FlowNodePtr::parent()
const {
327 return (FlowNode*)leaf->parent;
329 return node->parent();
332inline void FlowNodePtr::set_data(FlowNodeData data) {
334 leaf->node_data[0] = data;
336 node->node_data = data;
339inline void FlowNodePtr::set_parent(FlowNode* parent) {
341 leaf->parent = parent;
343 node->set_parent(parent);
Base class for Click elements.
Definition element.hh:42
Definition flow_level.hh:291
An IPv4 address.
Definition ipaddress.hh:16
A network packet.
Definition packet.hh:68
const unsigned char * data() const
Return the packet's data pointer.
Definition packet.hh:1207
A string of characters.
Definition string.hh:22
Flexible error handling classes.
Click's doubly-linked list container template.
The Packet class models packets in Click.
Classes for synchronizing among multiple CPUs, particularly in the Linux kernel.
The Timestamp class represents a moment or interval in time.
Click's vector container template.