예제 #1
0
/*
 * Delete single flow or all flows.
 *
 * When request->key is empty delete all flows
 */
static void
flow_cmd_del(struct dpdk_flow_message *request)
{
	struct dpdk_message reply = {0};
	struct flow_key empty = {0};
	int pos = 0;

	if (!memcmp(&request->key, &empty, sizeof(request->key))) {
		flow_table_del_all();
		reply.type = 0;
	} else {
		pos = flow_table_lookup(&request->key);
		if (pos < 0) {
			reply.type = ENOENT;
		} else {
			/* Retrieve flow stats*/
			flow_table_get_flow(&request->key,
			               NULL, &request->stats);
			flow_table_del_flow(&request->key);
			reply.type = 0;
		}
	}

	reply.flow_msg = *request;
	send_reply_to_vswitchd(&reply);
}
예제 #2
0
/*
 * Add or modify flow table entry.
 *
 * When modifying, the stats can be optionally cleared
 */
static void
flow_cmd_new(struct dpdk_flow_message *request)
{
	struct dpdk_message reply = {0};
	int pos = 0;

	pos = flow_table_lookup(&request->key);
	if (pos < 0) {
		if (request->flags & FLAG_CREATE) {
			flow_table_add_flow(&request->key, request->actions);
			reply.type = 0;
		} else {
			reply.type = ENOENT;
		}
	} else {
		if (request->flags & FLAG_REPLACE) {
			/* Retrieve flow stats*/
			flow_table_get_flow(&request->key,
			                    NULL, &request->stats);
			/* Depending on the value of request->clear we will
			 * either update or keep the same stats
			 */
			flow_table_mod_flow(&request->key,
			         request->actions, request->clear);
			reply.type = 0;
		} else {
			reply.type = EEXIST;
		}
	}

	reply.flow_msg = *request;

	send_reply_to_vswitchd(&reply);
}
예제 #3
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.");
}