/* * 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); }
/* 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 ); }