void indigo_core_table_register(uint8_t table_id, const char *name, const indigo_core_table_ops_t *ops, void *priv) { AIM_TRUE_OR_DIE(strlen(name) <= OF_MAX_TABLE_NAME_LEN); list_links_t *cur, *next; ft_entry_t *entry; FT_ITER(ind_core_ft, entry, cur, next) { if (entry->table_id == table_id) { ind_core_flow_entry_delete(entry, OF_FLOW_REMOVED_REASON_DELETE, INDIGO_CXN_ID_UNSPECIFIED); } } ind_core_table_t *table = aim_zmalloc(sizeof(*table)); strncpy(table->name, name, sizeof(table->name)); table->ops = ops; table->priv = priv; table->num_flows = 0; AIM_TRUE_OR_DIE(ind_core_tables[table_id] == NULL); ind_core_tables[table_id] = table; ind_core_num_tables_registered++; AIM_LOG_VERBOSE("Registered flowtable \"%s\" with table id %d", name, table_id); }
static void expire_flow(ft_entry_t *entry, int reason) { if (reason == INDIGO_FLOW_REMOVED_HARD_TIMEOUT) { LOG_TRACE("Hard TO (%d): " INDIGO_FLOW_ID_PRINTF_FORMAT, entry->hard_timeout, INDIGO_FLOW_ID_PRINTF_ARG(entry->id)); ind_core_flow_entry_delete(entry, reason, INDIGO_CXN_ID_UNSPECIFIED); } else if (reason == OF_FLOW_REMOVED_REASON_IDLE_TIMEOUT) { int rv; bool hit; /* Get hit status for idle timeouts */ ind_core_table_t *table = ind_core_table_get(entry->table_id); if (table != NULL) { rv = table->ops->entry_hit_status_get(table->priv, INDIGO_CXN_ID_UNSPECIFIED, entry->priv, &hit); } else { rv = indigo_fwd_flow_hit_status_get(entry->id, &hit); } if (rv != INDIGO_ERROR_NONE) { LOG_ERROR("Failed to get hit status for flow " INDIGO_FLOW_ID_PRINTF_FORMAT": %s", entry->id, indigo_strerror(rv)); return; } if (hit || entry->flags & OF_FLOW_MOD_FLAG_BSN_SEND_IDLE) { /* Reinsert entry into the expiration list */ entry->last_counter_change = INDIGO_CURRENT_TIME; ind_core_expiration_remove(entry); ind_core_expiration_add(entry); } if (!hit) { if (entry->flags & OF_FLOW_MOD_FLAG_BSN_SEND_IDLE) { send_idle_notification(entry); } else { LOG_TRACE("Idle TO (%d): " INDIGO_FLOW_ID_PRINTF_FORMAT, entry->idle_timeout, INDIGO_FLOW_ID_PRINTF_ARG(entry->id)); ind_core_flow_entry_delete(entry, reason, INDIGO_CXN_ID_UNSPECIFIED); } } } }
void indigo_core_table_unregister(uint8_t table_id) { ind_core_table_t *table = ind_core_tables[table_id]; AIM_TRUE_OR_DIE(table != NULL); list_links_t *cur, *next; ft_entry_t *entry; FT_ITER(ind_core_ft, entry, cur, next) { if (entry->table_id == table_id) { ind_core_flow_entry_delete(entry, OF_FLOW_REMOVED_REASON_DELETE, INDIGO_CXN_ID_UNSPECIFIED); } } aim_free(table); ind_core_tables[table_id] = NULL; ind_core_num_tables_registered--; }
/** * Timer operation to expire flows. * * Calls indigo_fwd_flow_stats_get for each flow in the table. The expiration * is done in flow_expiration_timer_cb when the reply is received. * * Ignore this call if the module is not enabled. */ static void flow_expiration_timer(void *cookie) { ft_entry_t *entry; list_links_t *cur, *next; indigo_time_t current_time = INDIGO_CURRENT_TIME; if (!ind_core_module_enabled) { return; } FT_ITER(ind_core_ft, entry, cur, next) { indigo_error_t rv; indigo_fi_flow_stats_t flow_stats; if (entry->hard_timeout > 0) { uint32_t delta; delta = INDIGO_TIME_DIFF_ms(entry->insert_time, current_time) / 1000; if (delta >= entry->hard_timeout) { LOG_TRACE("Hard TO (%d): " INDIGO_FLOW_ID_PRINTF_FORMAT, entry->hard_timeout, INDIGO_FLOW_ID_PRINTF_ARG(entry->id)); ind_core_flow_entry_delete(entry, INDIGO_FLOW_REMOVED_HARD_TIMEOUT, INDIGO_CXN_ID_UNSPECIFIED); continue; } } /* Update local copy of counters */ /* Only used currently for idle timeouts */ if (entry->idle_timeout > 0) { rv = indigo_fwd_flow_stats_get(entry->id, &flow_stats); if (rv != INDIGO_ERROR_NONE) { LOG_ERROR("Failed to get stats for flow "INDIGO_FLOW_ID_PRINTF_FORMAT": %d", entry->id, rv); continue; } if (entry->packets != flow_stats.packets) { entry->packets = flow_stats.packets; entry->last_counter_change = current_time; } if (entry->bytes != flow_stats.bytes) { entry->bytes = flow_stats.bytes; entry->last_counter_change = current_time; } } if (entry->idle_timeout > 0) { uint32_t delta; delta = INDIGO_TIME_DIFF_ms(entry->last_counter_change, current_time) / 1000; if (delta >= entry->idle_timeout) { LOG_TRACE("Idle TO (%d): " INDIGO_FLOW_ID_PRINTF_FORMAT, entry->idle_timeout, INDIGO_FLOW_ID_PRINTF_ARG(entry->id)); ind_core_flow_entry_delete(entry, INDIGO_FLOW_REMOVED_IDLE_TIMEOUT, INDIGO_CXN_ID_UNSPECIFIED); continue; } } }