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