예제 #1
0
void
indigo_core_flow_removed(indigo_fi_flow_removed_t reason,
                         indigo_fi_flow_stats_t *stats)
{
    ft_entry_t *entry;

    if (!ind_core_init_done) {
        return;
    }

    LOG_TRACE("Async flow removed. reason %d. id "
              INDIGO_FLOW_ID_PRINTF_FORMAT, reason,
              INDIGO_FLOW_ID_PRINTF_ARG((indigo_cookie_t) stats->flow_id));

    /* After entry look up, this looks like ind_core_flow_entry_delete */
    entry = ft_lookup(ind_core_ft, stats->flow_id);
    if (entry == NULL) {
        LOG_TRACE("Async flow removed: did not find entry in SM table. id "
                  INDIGO_FLOW_ID_PRINTF_FORMAT,
                  INDIGO_FLOW_ID_PRINTF_ARG((indigo_cookie_t) stats->flow_id));
        return;
    }

    process_flow_removal(entry, stats, reason);
}
예제 #2
0
static void
process_flow_removal(ft_entry_t *entry,
                     indigo_fi_flow_stats_t *final_stats,
                     indigo_fi_flow_removed_t reason)
{
    indigo_error_t rv;

    if (entry->flags & OF_FLOW_MOD_FLAG_SEND_FLOW_REM) {
        /* See OF spec 1.0.1, section 3.5, page 6 */
        if (reason != INDIGO_FLOW_REMOVED_OVERWRITE) {
            if (final_stats != NULL) {
                INDIGO_ASSERT(final_stats->flow_id == entry->id);
                entry->packets = final_stats->packets;
                entry->bytes = final_stats->bytes;
            } else {
                entry->packets = (uint64_t)-1;
                entry->bytes = (uint64_t)-1;
            }

            send_flow_removed_message(entry, reason);
        }
    }

    rv = ft_delete(ind_core_ft, entry);
    if (rv != INDIGO_ERROR_NONE) {
        LOG_ERROR("Error deleting flow from state mgr. id: "
                  INDIGO_FLOW_ID_PRINTF_FORMAT,
                  INDIGO_FLOW_ID_PRINTF_ARG(entry->id));
    }
    LOG_TRACE("Flow table now has %d entries",
              FT_STATUS(ind_core_ft)->current_count);
}
예제 #3
0
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);
            }
        }
    }
}
예제 #4
0
void
ind_core_flow_entry_delete(ft_entry_t *entry, indigo_fi_flow_removed_t reason,
                           indigo_cxn_id_t cxn_id)
{
    indigo_error_t rv;
    indigo_fi_flow_stats_t flow_stats;

    LOG_TRACE("Removing flow " INDIGO_FLOW_ID_PRINTF_FORMAT,
              INDIGO_FLOW_ID_PRINTF_ARG(entry->id));

    rv = indigo_fwd_flow_delete(entry->id, &flow_stats);
    if (rv != INDIGO_ERROR_NONE) {
        LOG_ERROR("Error deleting flow, id " INDIGO_FLOW_ID_PRINTF_FORMAT,
                  INDIGO_FLOW_ID_PRINTF_ARG(entry->id));
        /* Ignoring failure */
    }

    process_flow_removal(entry, &flow_stats, reason);
}
예제 #5
0
/**
 * 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;
            }
        }
    }