6 #include "../../../platform/memory.h"
7 #include "../../../platform/lock.h"
8 #include "../../../platform/likely.h"
9 #include "../../../platform/timing.h"
10 #include "../../../util/logging.h"
13 #if ! OF1X_TIMER_STATIC_ALLOCATION_SLOTS
23 entry->timer_info.hard_timeout = hard_timeout;
24 entry->timer_info.idle_timeout = idle_timeout;
25 entry->timer_info.hard_timer_entry = NULL;
26 entry->timer_info.idle_timer_entry = NULL;
33 bool __of1x_time_is_later(
struct timeval *a,
struct timeval *b){
34 if(a->tv_sec > b->tv_sec){
38 if (a->tv_sec == b->tv_sec){
39 if(a->tv_usec > b->tv_usec){
58 ROFL_PIPELINE_DEBUG(
"Timer group list is empty\n");
61 #if OF1X_TIMER_STATIC_ALLOCATION_SLOTS
63 for(i=0;i<OF1X_TIMER_GROUPS_MAX;i++)
65 ROFL_PIPELINE_DEBUG(
"timer group on position %p\n", &(tg[i]));
66 ROFL_PIPELINE_DEBUG(
" [%p] TO:%"PRIu64
" Nent:%d h:%p t:%p\n",&(tg[i]), tg[i].timeout,
67 tg[i].list.num_of_timers, tg[i].list.head, tg[i].list.tail);
68 for(et=tg[i].list.head; et; et=et->next)
69 ROFL_PIPELINE_DEBUG(
" [%p] fe:%p prev:%p next:%p tg:%p\n", et,et->entry, et->prev, et->next, et->group);
74 ROFL_PIPELINE_DEBUG(
"NOT the first group!!\n");
75 for(;tg!=NULL;tg=tg->next)
77 ROFL_PIPELINE_DEBUG(
"timer group on position %p\n", tg);
78 ROFL_PIPELINE_DEBUG(
" [%p] TO:%"PRIu64
" next:%p prev:%p Nent:%d h:%p t:%p\n",tg, tg->timeout, tg->next, tg->prev,
79 tg->list.num_of_timers, tg->list.head, tg->list.tail);
80 for(et=tg->list.head; et; et=et->next)
81 ROFL_PIPELINE_DEBUG(
" [%p] fe:%p prev:%p next:%p tg:%p\n", et,et->entry, et->prev, et->next, et->group);
92 uint64_t tmp = time->tv_sec;
94 return tmp + (time->tv_usec/1000);
102 uint64_t expiration_time_ms;
106 expiration_time_ms = (now->tv_sec+timeout)*1000+now->tv_usec/1000;
109 if(expiration_time_ms%OF1X_TIMER_SLOT_MS)
110 return (expiration_time_ms/OF1X_TIMER_SLOT_MS + 1)*OF1X_TIMER_SLOT_MS;
112 return expiration_time_ms;
115 #if OF1X_TIMER_STATIC_ALLOCATION_SLOTS
125 uint64_t time_next_slot;
132 if(unlikely(table->timers == NULL))
135 for(i=0; i<OF1X_TIMER_GROUPS_MAX;i++)
137 table->timers[i].timeout=time_next_slot+OF1X_TIMER_SLOT_MS*i;
138 table->timers[i].list.num_of_timers = 0;
139 table->timers[i].list.head = table->timers[i].list.tail = NULL;
141 table->current_timer_group=0;
166 if(__of1x_destroy_all_entries_from_timer_group(tg, pipeline, id_table)!=ROFL_SUCCESS)
167 ROFL_PIPELINE_DEBUG(
"ERROR in destroying timer group\n");
169 tg->timeout += OF1X_TIMER_SLOT_MS*OF1X_TIMER_GROUPS_MAX;
170 tg->list.num_of_timers=0;
171 tg->list.head = tg->list.tail = NULL;
173 pipeline->tables[id_table].current_timer_group++;
174 if(pipeline->tables[id_table].current_timer_group>=OF1X_TIMER_GROUPS_MAX)
175 pipeline->tables[id_table].current_timer_group=0;
189 if(unlikely(new_group == NULL))
191 ROFL_PIPELINE_DEBUG(
"<%s:%d> Error allocating memory\n",__func__,__LINE__);
194 new_group->timeout = timeout;
195 new_group->list.num_of_timers=0;
196 new_group->list.head=NULL;
197 new_group->list.tail=NULL;
200 new_group->prev=tg_prev;
201 new_group->next=tg_next;
204 if (tg_next) tg_next->prev=new_group;
206 if (tg_prev) tg_prev->next=new_group;
208 if(table->timers == tg_next)
209 table->timers = new_group;
221 (tg->prev)->next=tg->next;
223 if(table->timers == tg)
224 table->timers = tg->next;
226 (tg->next)->prev=tg->prev;
240 if(unlikely(new_entry==NULL))
242 ROFL_PIPELINE_DEBUG(
"<%s:%d> Error allocating memory\n",__func__,__LINE__);
245 new_entry->entry = entry;
246 new_entry->group = tg;
249 new_entry->next=NULL;
254 new_entry->prev=tg->list.tail;
256 tg->list.tail->next=new_entry;
260 new_entry->prev=NULL;
263 tg->list.head = new_entry;
267 tg->list.tail = new_entry;
269 tg->list.num_of_timers++;
271 new_entry->type=is_idle;
274 entry->timer_info.idle_timer_entry=new_entry;
276 entry->timer_info.hard_timer_entry=new_entry;
288 if(likely(entry!=NULL))
290 if(!entry->next && !entry->prev)
292 entry->group->list.head=NULL;
293 entry->group->list.tail=NULL;
295 else if(!entry->prev)
297 entry->group->list.head=entry->next;
298 entry->next->prev = NULL;
300 else if(!entry->next)
302 entry->group->list.tail=entry->prev;
303 entry->prev->next = NULL;
307 entry->next->prev = entry->prev;
308 entry->prev->next = entry->next;
311 entry->group->list.num_of_timers--;
312 #if ! OF1X_TIMER_STATIC_ALLOCATION_SLOTS
314 if(entry->group->list.num_of_timers == 0)
315 __of1x_destroy_timer_group(entry->group,table);
323 ROFL_PIPELINE_DEBUG(
"<%s:%d> Not a valid timer entry %p\n",__func__,__LINE__,entry);
338 if(unlikely(entry->table==NULL))
341 if(entry->timer_info.hard_timeout){
342 if(__of1x_destroy_single_timer_entry_clean(entry->timer_info.hard_timer_entry, entry->table)!=ROFL_SUCCESS)
344 entry->timer_info.hard_timer_entry = NULL;
347 if(entry->timer_info.idle_timeout){
348 if(__of1x_destroy_single_timer_entry_clean(entry->timer_info.idle_timer_entry, entry->table)!=ROFL_SUCCESS)
350 entry->timer_info.idle_timer_entry = NULL;
353 #if DEBUG_NO_REAL_PIPE
366 struct timeval system_time;
367 uint64_t expiration_time;
371 __of1x_stats_flow_consolidate(&entry_timer->entry->stats, &consolidated_stats);
373 if(consolidated_stats.packet_count == entry_timer->entry->timer_info.last_packet_count)
376 #ifdef DEBUG_NO_REAL_PIPE
377 ROFL_PIPELINE_DEBUG(
"NOT erasing real entries of table \n");
382 __of1x_remove_specific_flow_entry_table(pipeline, id_table, entry_timer->entry, OF1X_FLOW_REMOVE_IDLE_TIMEOUT, MUTEX_ALREADY_ACQUIRED_BY_TIMER_EXPIRATION);
387 entry_timer->entry->timer_info.last_packet_count = consolidated_stats.packet_count;
393 #if OF1X_TIMER_STATIC_ALLOCATION_SLOTS
395 int slot_delta = expiration_time - pipeline->tables[id_table].timers[pipeline->tables[id_table].current_timer_group].timeout;
396 int slot_position = (pipeline->tables[id_table].current_timer_group + slot_delta/OF1X_TIMER_SLOT_MS) % OF1X_TIMER_GROUPS_MAX;
397 if(__of1x_entry_timer_init(&(pipeline->tables[id_table].timers[slot_position]), entry_timer->entry, IDLE_TO)==NULL)
401 of1x_timer_group_t * tg_iterator = __of1x_dynamic_slot_search(pipeline->tables[id_table], expiration_time);
402 if(tg_iterator==NULL)
405 if(__of1x_entry_timer_init(tg_iterator, entry_timer->entry, IDLE_TO) == NULL)
410 __of1x_destroy_single_timer_entry_clean(entry_timer, &pipeline->tables[id_table]);
425 if(tg->list.num_of_timers>0 && tg->list.head){
426 while( (entry_iterator = tg->list.head) != NULL){
429 if(entry_iterator->type == IDLE_TO){
430 if(__of1x_reschedule_idle_timer(entry_iterator, pipeline, id_table)!=ROFL_SUCCESS)
433 #ifdef DEBUG_NO_REAL_PIPE
434 ROFL_PIPELINE_DEBUG(
"NOT erasing real entries of table \n");
440 __of1x_remove_specific_flow_entry_table(pipeline, id_table,entry_iterator->entry, OF1X_FLOW_REMOVE_HARD_TIMEOUT, MUTEX_ALREADY_ACQUIRED_BY_TIMER_EXPIRATION);
448 #if ! OF1X_TIMER_STATIC_ALLOCATION_SLOTS
459 for(tg_iterator = table->timers; tg_iterator && tg_iterator->timeout<expiration_time && tg_iterator->next; tg_iterator=tg_iterator->next);
465 table->timers = __of1x_timer_group_init(expiration_time,NULL,NULL, table);
466 if(table->timers == NULL)
469 tg_iterator = table->timers;
471 else if(tg_iterator->timeout>expiration_time)
474 tg_iterator = __of1x_timer_group_init(expiration_time,tg_iterator,tg_iterator->prev, table);
475 if(tg_iterator == NULL)
478 else if(tg_iterator->timeout < expiration_time && !tg_iterator->next)
481 tg_iterator = __of1x_timer_group_init(expiration_time,NULL, tg_iterator, table);
482 if(tg_iterator == NULL)
487 if (!(tg_iterator->timeout==expiration_time))
490 ROFL_PIPELINE_DEBUG(
"<%s:%d> No proper position for this entry found\n",__func__, __LINE__);
501 uint64_t expiration_time;
505 #if OF1X_TIMER_STATIC_ALLOCATION_SLOTS
507 if(timeout > OF1X_TIMER_GROUPS_MAX)
509 ROFL_PIPELINE_DEBUG(
"Timeout value excedded maximum value (hto=%d, MAX=%d)\n", timeout,OF1X_TIMER_GROUPS_MAX);
514 int slot_delta = expiration_time - table->timers[table->current_timer_group].timeout;
518 int slot_position = (table->current_timer_group+(slot_delta/OF1X_TIMER_SLOT_MS))%(OF1X_TIMER_GROUPS_MAX);
519 if(__of1x_entry_timer_init(&(table->timers[slot_position]), entry, is_idle)==NULL)
525 if (tg_iterator==NULL)
529 if(__of1x_entry_timer_init(tg_iterator, entry, is_idle, NULL) == NULL)
541 if(entry->timer_info.idle_timeout)
543 res = __of1x_add_single_timer(table, entry->timer_info.idle_timeout, entry, IDLE_TO);
544 if(res == ROFL_FAILURE)
549 if(entry->timer_info.hard_timeout)
551 res = __of1x_add_single_timer(table, entry->timer_info.hard_timeout, entry, HARD_TO);
552 if(res == ROFL_FAILURE)
561 void __of1x_process_pipeline_tables_timeout_expirations(
of1x_pipeline_t *
const pipeline){
565 struct timeval system_time;
569 for(i=0;i<pipeline->num_of_tables;i++)
573 #if OF1X_TIMER_STATIC_ALLOCATION_SLOTS
574 while(table->timers[table->current_timer_group].timeout<=now)
577 __of1x_timer_group_rotate(pipeline,&(table->timers[table->current_timer_group]),i);
581 for(slot_it=table->timers; slot_it; slot_it=next)
583 if(now<slot_it->timeout)
586 if(__of1x_destroy_all_entries_from_timer_group(slot_it, table)!=ROFL_SUCCESS)
588 ROFL_PIPELINE_DEBUG(
"Error while destroying timer group\n");
592 next = slot_it->next;
594 __of1x_destroy_timer_group(slot_it, table);
rofl_result_t __of1x_destroy_timer_entries(struct of1x_flow_entry *entry)
of1x_destroy_timer_entry When a flow entry is removed from the table this function will be called in ...
OpenFlow v1.0, 1.2 and 1.3.2 pipeline abstraction.
void __of1x_timer_group_static_destroy(struct of1x_flow_table *table)
of1x_timer_group_static_destroy Destroys the timers table initializes the values for the entry lists ...
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
OpenFlow v1.0, 1.2 and 1.3.2 flow entry structure.
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
void __of1x_fill_new_timer_entry_info(struct of1x_flow_entry *entry, uint32_t hard_timeout, uint32_t idle_timeout)
of1x_fill_new_timer_entry_info initialize the values for a new the timer entry
OpenFlow v1.0, 1.2 and 1.3.2 timers subsystem.
void __of1x_dump_timers_structure(of1x_timer_group_t *timer_group)
of1x_dump_timers_structure this function is ment to show the timer groups existing and the entries re...
OpenFlow v1.0, 1.2 and 1.3.2 flow entry abstraction.
OpenFlow v1.0, 1.2 and 1.3.2 pipeline abstraction data structure.
rofl_result_t __of1x_timer_group_static_init(struct of1x_flow_table *table)
of1x_timer_group_static_init initializes the timeout values initializes the values for the entry list...
uint64_t __of1x_get_expiration_time_slotted(uint32_t timeout, struct timeval *now)
of1x_get_expiration_time_slotted
uint64_t __of1x_get_time_ms(struct timeval *time)
transforms the timeval to a single uint64_t unit time in miliseconds