Esempio n. 1
0
/* Try to delete all flows, which should succeed */
static void
test_flow_table_del_all(int argc, char *argv[])
{
	struct flow_key key1 = {1};
	struct flow_key key2 = {2};
	struct flow_key key_check = {0};
	struct action action_multiple[MAX_ACTIONS] = {0};
	struct action action_check[MAX_ACTIONS] = {0};
	struct flow_stats stats_check = {0};
	int ret = 0;

	flow_table_init();

	action_output_build(&action_multiple[0], 1);
	action_output_build(&action_multiple[1], 2);
	action_null_build(&action_multiple[2]);
	/* Add two flowss to be deleted */
	flow_table_add_flow(&key1, action_multiple);
	ret = flow_table_get_flow(&key1, NULL, NULL);
	assert(ret >= 0);
	flow_table_add_flow(&key2, action_multiple);
	ret = flow_table_get_flow(&key2,  NULL, NULL);
	assert(ret >= 0);
	/* delete all flows and ensure flows are deleted */
	flow_table_del_all();
	ret = flow_table_get_first_flow(&key_check, action_check, &stats_check);
	assert(ret < 0);
}
Esempio n. 2
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);
}
Esempio n. 3
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);
}
Esempio n. 4
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};
	int32_t pos = 0;

	if (!memcmp(&request->key, &empty, sizeof(request->key))) {
		/* if flow is empty, delete all flows */
		for (pos = 0; pos < MAX_FLOWS; pos++) {
			if (flow_table->used[pos]) {
				rte_hash_del_key(handle, &request->key);
				flow_table_del_flow(pos);
			}
		}
		reply.type = 0;
	} else {
		/* delete specified flow */
		pos = rte_hash_del_key(handle, &request->key);

		if (pos < 0) {
			reply.type = ENOENT;
			}
		else {
			flow_table_get_flow(pos, NULL, NULL, &request->stats);
			flow_table_del_flow(pos);
			reply.type = 0;
		}
	}

	reply.flow_msg = *request;

	send_reply_to_vswitchd(&reply);
}
Esempio n. 5
0
/* Try to modify a flow, which should succeed */
static void
test_flow_table_mod_flow(int argc, char *argv[])
{
	struct flow_key key1 = {1};
	struct action action_multiple[MAX_ACTIONS] = {0};
	struct action action_check[MAX_ACTIONS] = {0};
	struct flow_stats stats_zero = {0};
	struct flow_stats stats_check = {0};
	int ret = 0;

	flow_table_init();

	/* add a flow with 2 actions */
	action_output_build(&action_multiple[0], 2);
	action_output_build(&action_multiple[1], 1);
	action_null_build(&action_multiple[2]);
	flow_table_add_flow(&key1, action_multiple);
	action_output_build(&action_multiple[0], 1);
	action_null_build(&action_multiple[1]);
	/*modify it to only have 1 action */
	flow_table_mod_flow(&key1, action_multiple, true);

	ret = flow_table_get_flow(&key1, action_check, &stats_check);
	assert(ret >= 0);
	assert(memcmp(&action_multiple[0], action_check, sizeof(struct action)) == 0);
	/* check that our flow now only has one entry */
	assert(action_check[1].type == ACTION_NULL);
	assert(memcmp(&stats_zero, &stats_check , sizeof(struct flow_stats)) == 0 );
}
Esempio n. 6
0
/*
 * Return flow entry to vswitchd if it exists
 */
static void
flow_cmd_get(struct dpdk_flow_message *request)
{
	struct dpdk_message reply = {0};
	int ret = 0;

	ret = flow_table_get_flow(&request->key, request->actions, &request->stats);
	if (ret < 0) {
		reply.type = ENOENT;
	} else {
		reply.type = 0;
	}

	reply.flow_msg = *request;
	send_reply_to_vswitchd(&reply);
}
Esempio n. 7
0
/*
 * Dump all flows.
 *
 * The message that is received contains the key for the previously dumped
 * flow entry. If the key is zero then we are dumping the first entry. We
 * reply with EOF when we have dumped all flows
 *
 */
static void
flow_cmd_dump(struct dpdk_flow_message *request)
{
	struct dpdk_message reply = {0};
	struct flow_key empty = {0};
	int32_t pos = 0;

	if (!memcmp(&request->key, &empty, sizeof(request->key))) {
		/*
		 * if flow is empty, it is first call of dump(),
		 * and start searching from the first rule
		 */
		pos = 0;
	} else {
		/* last dumped flow */
		pos = rte_hash_lookup(handle, &request->key);

		if (pos < 0) {
			/* send error reply - the flow must be in the flow table */
			reply.type = ENOENT;
			goto out;
		}
		/* search starting from the next flow */
		pos++;
	}

	/* find next using flow */
	for(;pos < MAX_FLOWS && !flow_table->used[pos]; pos++)
		;

	if (pos < MAX_FLOWS) {
		flow_table_get_flow(pos, &request->key, &request->action, &request->stats);
		reply.type = 0;
	} else {
		/* it was last flow, send message that no more flows here */
		reply.type = EOF;
	}

out:
	reply.flow_msg = *request;

	send_reply_to_vswitchd(&reply);
}
Esempio n. 8
0
/*
 * Return flow entry to vswitchd if it exists
 */
static void
flow_cmd_get(struct dpdk_flow_message *request)
{
	struct dpdk_message reply = {0};
	int32_t pos = 0;

	pos = rte_hash_lookup(handle, &request->key);

	if (pos < 0) {
		reply.type = ENOENT;
	} else {
		flow_table_get_flow(pos, NULL, &request->action, &request->stats);
		reply.type = 0;
	}

	reply.flow_msg = *request;

	send_reply_to_vswitchd(&reply);
}
Esempio n. 9
0
/*
 * This function takes a packet and routes it as per the flow table.
 */
void
switch_packet(struct rte_mbuf *pkt, uint8_t in_port)
{
	int ret = 0;
	struct dpdk_upcall info = {0};
	struct action action = {0};

	flow_key_extract(pkt, in_port, &info.key);

	ret = flow_table_get_flow(&info.key, &action, NULL);
	if (ret >= 0) {
		flow_table_update_stats(&info.key, pkt);
		action_execute(&action, pkt);
	} else {
		/* flow table miss, send unmatched packet to the daemon */
		info.cmd = PACKET_CMD_MISS;
		send_packet_to_vswitchd(pkt, &info);
	}
}
Esempio n. 10
0
/* Try to get a flow, which should succeed */
static void
test_flow_table_get_flow(int argc, char *argv[])
{
	struct flow_key key1 = {1};
	struct action action_multiple[MAX_ACTIONS] = {0};
	struct action action_check[MAX_ACTIONS] = {0};
	struct flow_stats stats_zero = {0};
	struct flow_stats stats_check = {0};
	int ret = 0;

	flow_table_init();

	action_output_build(&action_multiple[0], 1);
	action_output_build(&action_multiple[1], 2);
	action_null_build(&action_multiple[2]);
	flow_table_add_flow(&key1, action_multiple);
	ret = flow_table_get_flow(&key1, action_check, &stats_check);
	assert(ret >= 0);
	assert(memcmp(&action_multiple[0], action_check, sizeof(struct action)) == 0);
	assert(memcmp(&action_multiple[1], &action_check[1], sizeof(struct action)) == 0);
	assert(memcmp(&stats_zero, &stats_check , sizeof(struct flow_stats)) == 0 );
}
Esempio n. 11
0
/* Try to delete a normal flow and a non-existent flow, which should succeed
 * and fail with -1 respectively */
static void
test_flow_table_del_flow(int argc, char *argv[])
{
	struct flow_key key1 = {1};
	struct action action_multiple[MAX_ACTIONS] = {0};
	int ret = 0;

	flow_table_init();

	/* TODO: Break this into multiple tests? */
	action_output_build(&action_multiple[0], 1);
	action_output_build(&action_multiple[1], 2);
	action_null_build(&action_multiple[2]);
	flow_table_add_flow(&key1, action_multiple);
	ret = flow_table_del_flow(&key1);
	assert(ret >= 0);
	/* check no flow match */
	ret = flow_table_get_flow(&key1, NULL, NULL);
	assert(ret < 0);
	ret = flow_table_del_flow(&key1);
	assert(ret < 0);
}