/* Execute a group entry of type FAILFAST. */
static void
execute_ff(struct group_entry *entry, struct packet *pkt) {
    size_t b  = select_from_ff_group(entry);

    if (b != -1) {
        struct ofl_bucket *bucket = entry->desc->buckets[b];
        struct packet *p = packet_clone(pkt);

        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
            char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp);
            VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b);
            free(b);
        }

        action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions);

        entry->stats->byte_count += p->buffer->size;
        entry->stats->packet_count++;
        entry->stats->counters[b]->byte_count += p->buffer->size;
        entry->stats->counters[b]->packet_count++;
        /* Cookie field is set 0xffffffffffffffff
           because we cannot associate to any
           particular flow */
        action_set_execute(p->action_set, p, 0xffffffffffffffff);
        packet_destroy(p);
    } else {
        VLOG_DBG_RL(LOG_MODULE, &rl, "No bucket in group.");
    }
}
/* Executes a group entry of type ALL. */
static void
execute_all(struct group_entry *entry, struct packet *pkt) {
    size_t i;

    /* TODO Zoltan: Currently packets are always cloned. However it should
     * be possible to see if cloning is necessary, or not, based on bucket actions. */
    for (i=0; i<entry->desc->buckets_num; i++) {
        struct ofl_bucket *bucket = entry->desc->buckets[i];
        struct packet *p = packet_clone(pkt);

        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
            char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp);
            VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b);
            free(b);
        }

        action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions);

        entry->stats->byte_count += p->buffer->size;
        entry->stats->packet_count++;
        entry->stats->counters[i]->byte_count += p->buffer->size;
        entry->stats->counters[i]->packet_count++;

        /* Cookie field is set 0xffffffffffffffff
           because we cannot associate to any
           particular flow */
        action_set_execute(p->action_set, p, 0xffffffffffffffff);

        packet_destroy(p);
    }
}
Example #3
0
/* Execute a group entry of type INDIRECT. */
static void
execute_indirect(struct group_entry *entry, struct packet *pkt) {

    if (entry->desc->buckets_num > 0) {
        struct ofl_bucket *bucket = entry->desc->buckets[0];
        struct packet *p = packet_clone(pkt);

        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
            char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp);
            VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b);
            free(b);
        }

        action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions);

        entry->stats->byte_count += p->buffer->size;
        entry->stats->packet_count++;
        entry->stats->counters[0]->byte_count += p->buffer->size;
        entry->stats->counters[0]->packet_count++;

        action_set_execute(p->action_set, p);
        packet_destroy(p);
    } else {
        VLOG_DBG_RL(LOG_MODULE, &rl, "No bucket in group.");
    }
}
Example #4
0
void
pipeline_process_packet(struct pipeline *pl, struct packet *pkt) {
    struct flow_table *table, *next_table;

    if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
        char *pkt_str = packet_to_string(pkt);
        VLOG_DBG_RL(LOG_MODULE, &rl, "processing packet: %s", pkt_str);
        free(pkt_str);
    }
 
    if (!packet_handle_std_is_ttl_valid(pkt->handle_std)) {
        if ((pl->dp->config.flags & OFPC_INVALID_TTL_TO_CONTROLLER) != 0) {
            VLOG_DBG_RL(LOG_MODULE, &rl, "Packet has invalid TTL, sending to controller.");
            
            send_packet_to_controller(pl, pkt, 0/*table_id*/, OFPR_INVALID_TTL);
        } else {
            VLOG_DBG_RL(LOG_MODULE, &rl, "Packet has invalid TTL, dropping.");
        }
        packet_destroy(pkt);
        return;
    }

    next_table = pl->tables[0];
    while (next_table != NULL) {
        struct flow_entry *entry;

        VLOG_DBG_RL(LOG_MODULE, &rl, "trying table %u.", next_table->stats->table_id);

        pkt->table_id = next_table->stats->table_id;
        table         = next_table;
        next_table    = NULL;
         
        entry = flow_table_lookup(table, pkt);
        if (entry != NULL) {
	        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
                char *m = ofl_structs_flow_stats_to_string(entry->stats, pkt->dp->exp);
                VLOG_DBG_RL(LOG_MODULE, &rl, "found matching entry: %s.", m);
                free(m);
            }

            execute_entry(pl, entry, &next_table, &pkt);
            /* Packet could be destroyed by a meter instruction */
            if (!pkt)
                return;
            
            if (next_table == NULL) {
               /* Cookie field is set 0xffffffffffffffff
                because we cannot associate it to any
                particular flow */
                action_set_execute(pkt->action_set, pkt, 0xffffffffffffffff);
                packet_destroy(pkt);
                return;
            }

        } else {
			/* OpenFlow 1.3 default behavior on a table miss */
			VLOG_DBG_RL(LOG_MODULE, &rl, "No matching entry found. Dropping packet.");
			packet_destroy(pkt);
			return;
        }
    }
    VLOG_WARN_RL(LOG_MODULE, &rl, "Reached outside of pipeline processing cycle.");
}