1 #include "of1x_loop_ma.h"
5 #include "../../of1x_pipeline.h"
6 #include "../../of1x_flow_table.h"
7 #include "../../of1x_flow_entry.h"
8 #include "../../of1x_match.h"
9 #include "../../of1x_group_table.h"
10 #include "../../of1x_instruction.h"
11 #include "../../../of1x_async_events_hooks.h"
12 #include "../../../../../platform/lock.h"
13 #include "../../../../../platform/likely.h"
14 #include "../../../../../platform/memory.h"
15 #include "../matching_algorithms.h"
16 #include "../../../../../util/logging.h"
18 #define LOOP_DESCRIPTION "The loop algorithm searches the list of entries by its priority order. On the worst case the performance is o(N) with the number of entries"
37 case OF1X_FLOW_REMOVE_DELETE:
38 ROFL_PIPELINE_DEBUG(
"[flowmod-remove(%p)] Existing entry (%p) will be removed\n", entry, it);
40 case OF1X_FLOW_REMOVE_IDLE_TIMEOUT:
41 ROFL_PIPELINE_DEBUG(
"[flowmod-remove] Removing entry(%p) due to IDLE timeout\n", it);
43 case OF1X_FLOW_REMOVE_HARD_TIMEOUT:
44 ROFL_PIPELINE_DEBUG(
"[flowmod-remove] Removing entry(%p) due to HARD timeout\n", it);
46 case OF1X_FLOW_REMOVE_GROUP_DELETE:
47 ROFL_PIPELINE_DEBUG(
"[flowmod-remove] Removing entry(%p) due to GROUP delete\n", it);
66 for(it=start_entry; it != NULL; it=it->next){
84 for(it=start_entry; it != NULL; it=it->next){
101 if( unlikely(table->num_of_entries == 0) )
105 if(unlikely(specific_entry->table != table))
107 if(specific_entry->prev && unlikely(specific_entry->prev->next != specific_entry))
109 if(specific_entry->next && unlikely(specific_entry->next->prev != specific_entry))
116 of1x_remove_flow_entry_table_trace(NULL, specific_entry, reason);
119 if(!specific_entry->prev){
121 if(specific_entry->next)
122 specific_entry->next->prev = NULL;
123 table->
entries = specific_entry->next;
126 specific_entry->prev->next = specific_entry->next;
127 if(specific_entry->next)
128 specific_entry->next->prev = specific_entry->prev;
130 table->num_of_entries--;
137 (*ma_hook_ptr)(specific_entry);
141 #ifdef ROFL_PIPELINE_LOCKLESS
142 tid_wait_all_not_present(&table->tid_presence_mask);
144 return __of1x_destroy_flow_entry_with_reason(specific_entry, reason);
154 if(unlikely(table->num_of_entries == OF1X_MAX_NUMBER_OF_TABLE_ENTRIES)){
155 return ROFL_OF1X_FM_FAILURE;
164 entry->table = table;
166 table->num_of_entries++;
170 (*ma_hook_ptr)(entry);
173 return ROFL_OF1X_FM_SUCCESS;
177 if(check_overlap && of1x_flow_table_loop_check_overlapping(table->
entries, entry,
false, OF1X_PORT_ANY, OF1X_GROUP_ANY))
178 return ROFL_OF1X_FM_OVERLAP;
182 existing = of1x_flow_table_loop_check_identical(table->
entries, entry, OF1X_PORT_ANY, OF1X_GROUP_ANY,
false);
185 ROFL_PIPELINE_DEBUG(
"[flowmod-add(%p)] Existing entry(%p) will be replaced by (%p)\n", entry, existing, entry);
189 ROFL_PIPELINE_DEBUG(
"[flowmod-add(%p)] Getting counters from (%p)\n", entry, existing);
190 __of1x_stats_copy_flow_stats(&existing->stats, &entry->stats);
197 for(it=table->
entries,prev=NULL; it!=NULL;prev=it,it=it->next){
199 if(it->priority < entry->priority || (it->priority == entry->priority && it->matches.num_elements <= entry->matches.num_elements) ){
215 entry->next = prev->next;
222 prev->next->prev = entry;
231 table->num_of_entries++;
234 entry->table = table;
238 ROFL_PIPELINE_DEBUG(
"[flowmod-add(%p)] Removing old entry (%p)\n", entry, existing);
239 #ifdef ROFL_PIPELINE_LOCKLESS
240 tid_wait_all_not_present(&table->tid_presence_mask);
243 if(of1x_remove_flow_entry_table_specific_imp(table,existing, OF1X_FLOW_REMOVE_NO_REASON, ma_hook_ptr) != ROFL_SUCCESS){
250 (*ma_hook_ptr)(entry);
253 return ROFL_OF1X_FM_SUCCESS;
259 entry->next = entry->prev = NULL;
267 entry->table = table;
284 table->num_of_entries++;
288 ROFL_PIPELINE_DEBUG(
"[flowmod-add(%p)] Removing old entry (%p)\n", entry, existing);
289 #ifdef ROFL_PIPELINE_LOCKLESS
290 tid_wait_all_not_present(&table->tid_presence_mask);
293 if(unlikely(of1x_remove_flow_entry_table_specific_imp(table,existing, OF1X_FLOW_REMOVE_NO_REASON, ma_hook_ptr) != ROFL_SUCCESS)){
300 (*ma_hook_ptr)(entry);
303 return ROFL_OF1X_FM_SUCCESS;
318 of_version_t ver = table->pipeline->sw->of_ver;
320 if(table->num_of_entries == 0)
324 for(it=table->
entries; it; it=it_next){
329 if( strict == STRICT ){
333 of1x_remove_flow_entry_table_trace(entry, it, reason);
335 if(of1x_remove_flow_entry_table_specific_imp(table, it, reason, ma_hook_ptr) != ROFL_SUCCESS){
345 of1x_remove_flow_entry_table_trace(entry, it, reason);
347 if(of1x_remove_flow_entry_table_specific_imp(table, it, reason, ma_hook_ptr) != ROFL_SUCCESS){
379 if( unlikely( (entry&&specific_entry) ) || unlikely( (!entry && !specific_entry) ) )
383 return of1x_remove_flow_entry_table_non_specific_imp(table, entry, strict, out_port, out_group, reason, ma_hook_ptr);
385 return of1x_remove_flow_entry_table_specific_imp(table, specific_entry, reason, ma_hook_ptr);
396 return_value = of1x_add_flow_entry_table_imp(table, entry, check_overlap, reset_counts, ma_hook_ptr);
404 return __of1x_add_flow_entry_loop(table, entry, check_overlap, reset_counts, NULL);
416 for(it=table->
entries; it; it=it->next){
418 if( strict == STRICT ){
423 if(ma_modify_hook_ptr)
424 (*ma_modify_hook_ptr)(entry);
429 ROFL_PIPELINE_DEBUG(
"[flowmod-modify(%p)] Existing entry (%p) will be updated with (%p)\n", entry, it, entry);
431 if(__of1x_update_flow_entry(it, entry, reset_counts) != ROFL_SUCCESS)
440 if(ma_modify_hook_ptr)
441 (*ma_modify_hook_ptr)(entry);
446 ROFL_PIPELINE_DEBUG(
"[flowmod-modify(%p)] Existing entry (%p) will be updated with (%p)\n", entry, it, entry);
448 if(__of1x_update_flow_entry(it, entry, reset_counts) != ROFL_SUCCESS)
460 return (rofl_result_t)__of1x_add_flow_entry_loop(table, entry,
false, reset_counts, ma_add_hook_ptr);
463 ROFL_PIPELINE_DEBUG(
"[flowmod-modify(%p)] Deleting modifying flowmod \n", entry);
472 return __of1x_modify_flow_entry_loop(table, entry, strict, reset_counts, NULL, NULL);
478 rofl_result_t result;
485 result = of1x_remove_flow_entry_table_imp(table, entry, specific_entry, out_port, out_group,reason, strict, ma_hook_ptr);
496 return __of1x_remove_flow_entry_loop(table, entry, specific_entry, strict, out_port, out_group, reason, mutex_acquired, NULL);
504 rofl_result_t of1x_get_flow_stats_loop(
struct of1x_flow_table *
const table,
506 uint64_t cookie_mask,
514 bool check_cookie = (table->pipeline->sw->of_ver != OF_VERSION_10);
516 if( unlikely(msg==NULL) || unlikely(table==NULL) )
521 flow_stats_entry.matches = *matches;
522 flow_stats_entry.cookie = cookie;
523 flow_stats_entry.cookie_mask = cookie_mask;
524 check_cookie = ( table->pipeline->sw->of_ver != OF_VERSION_10 );
531 for(entry = table->
entries; entry!=NULL; entry = entry->next){
540 flow_stats = __of1x_init_stats_single_flow_msg(entry);
546 __of1x_push_single_flow_stats_to_msg(msg, flow_stats);
557 rofl_result_t of1x_get_flow_aggregate_stats_loop(
struct of1x_flow_table *
const table,
559 uint64_t cookie_mask,
568 if( unlikely(msg==NULL) || unlikely(table==NULL) )
573 flow_stats_entry.matches = *matches;
574 flow_stats_entry.cookie = cookie;
575 flow_stats_entry.cookie_mask = cookie_mask;
576 check_cookie = ( table->pipeline->sw->of_ver != OF_VERSION_10 );
582 for(entry = table->
entries; entry!=NULL; entry = entry->next){
589 __of1x_stats_flow_consolidate(&entry->stats, &c);
591 msg->packet_count += c.packet_count;
592 msg->byte_count += c.byte_count;
614 for(entry = table->
entries;entry!=NULL;entry = entry->next){
616 bool has_group =
false;
618 for( it=entry->matches.head; it; it=it->next ){
619 if(__of1x_instructions_contain_group(entry, group_id)){
643 for(entry = table->
entries; entry; entry = next){
645 __of1x_destroy_flow_entry_with_reason(entry, OF1X_FLOW_REMOVE_NO_REASON);
654 OF1X_REGISTER_MATCHING_ALGORITHM(loop) = {
657 .destroy_hook = of1x_destroy_loop,
660 .add_flow_entry_hook = of1x_add_flow_entry_loop,
661 .modify_flow_entry_hook = of1x_modify_flow_entry_loop,
662 .remove_flow_entry_hook = of1x_remove_flow_entry_loop,
665 .get_flow_stats_hook = of1x_get_flow_stats_loop,
666 .get_flow_aggregate_stats_hook = of1x_get_flow_aggregate_stats_loop,
669 .find_entry_using_group_hook = of1x_find_entry_using_group_loop,
673 .description = LOOP_DESCRIPTION,
void plaftorm_of1x_add_entry_hook(of1x_flow_entry_t *new_entry)
It can be used by hardware or other software (non rofl-pipeline) pipelines, to install the new entry...
OpenFlow v1.0, 1.2 and 1.3.2 flow entry structure.
enum of1x_flow_remove_reason of1x_flow_remove_reason_t
Flow remove reasons (enum ofp_flow_removed_reason)
void platform_of1x_modify_entry_hook(of1x_flow_entry_t *old_entry, of1x_flow_entry_t *mod, int reset_count)
It can be used by hardware or other software (non rofl-pipeline) pipelines, to modify an entry (singl...
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
of1x_flow_removal_strictness
Flow removal operations strictness.
Single flow entry stats message.
bool __of1x_flow_entry_check_contained(of1x_flow_entry_t *const original, of1x_flow_entry_t *const subentry, bool check_priority, bool check_cookie, uint32_t out_port, uint32_t out_group, bool reverse_out_check)
Checks whether an entry is contained in the other.
bool __of1x_flow_entry_check_overlap(of1x_flow_entry_t *const original, of1x_flow_entry_t *const entry, bool check_priority, bool check_cookie, uint32_t out_port, uint32_t out_group)
Checks whether two entries overlap overlapping.
void platform_of1x_remove_entry_hook(of1x_flow_entry_t *entry)
It can be used by hardware or other software (non rofl-pipeline) pipelines, to remove an entry (singl...
Linked list containing all the individual flow stats.
enum rofl_of1x_fm_result rofl_of1x_fm_result_t
Extended flowmod return codes.
of1x_flow_entry_t * entries
This pointer may or may not be used depending on the matching algorithm.
void platform_of1x_update_stats_hook(of1x_flow_entry_t *entry)
It can be used by hardware or other software (non rofl-pipeline) pipelines, to update the stats of an...
rofl_result_t of1x_destroy_flow_entry(of1x_flow_entry_t *entry)
Destroy the flow entry, including stats, instructions and actions.
Aggregated flow stats message.
bool __of1x_flow_entry_check_equal(of1x_flow_entry_t *const original, of1x_flow_entry_t *const entry, uint32_t out_port, uint32_t out_group, bool check_cookie)
Checks if entry is identical to another one out_port and out_grouap are ALWAYS checked against origin...