int ofl_msg_free(struct ofl_msg_header *msg, struct ofl_exp *exp, char *errbuf) { switch (msg->type) { case OFPT_HELLO: { break; } case OFPT_ERROR: { return ofl_msg_free_error((struct ofl_msg_error *)msg); } case OFPT_ECHO_REQUEST: case OFPT_ECHO_REPLY: { free(((struct ofl_msg_echo *)msg)->data); break; } case OFPT_EXPERIMENTER: { if (exp == NULL || exp->msg == NULL || exp->msg->free == NULL) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Trying to free EXPERIMENTER message, but no callback was given"); } free(msg); return -1; } exp->msg->free((struct ofl_msg_experimenter *)msg); return 0; } case OFPT_FEATURES_REQUEST: { break; } case OFPT_FEATURES_REPLY: { struct ofl_msg_features_reply *rep = (struct ofl_msg_features_reply *)msg; OFL_UTILS_FREE_ARR_FUN(rep->ports, rep->ports_num, ofl_structs_free_port); break; } case OFPT_GET_CONFIG_REQUEST: { break; } case OFPT_GET_CONFIG_REPLY: { free(((struct ofl_msg_get_config_reply *)msg)->config); break; } case OFPT_SET_CONFIG: { free(((struct ofl_msg_set_config *)msg)->config); break; } case OFPT_PACKET_IN: { free(((struct ofl_msg_packet_in *)msg)->data); break; } case OFPT_FLOW_REMOVED: { return ofl_msg_free_flow_removed((struct ofl_msg_flow_removed *)msg, true, exp, errbuf); break; } case OFPT_PORT_STATUS: { free(((struct ofl_msg_port_status *)msg)->desc); break; } case OFPT_PACKET_OUT: { return ofl_msg_free_packet_out((struct ofl_msg_packet_out *)msg, true, exp, errbuf); } case OFPT_FLOW_MOD: { return ofl_msg_free_flow_mod((struct ofl_msg_flow_mod *)msg, true, true, exp, errbuf); } case OFPT_GROUP_MOD: { return ofl_msg_free_group_mod((struct ofl_msg_group_mod *)msg, true, exp, errbuf); } case OFPT_PORT_MOD: case OFPT_TABLE_MOD: { break; } case OFPT_PROCESSOR_MOD: { return ofl_msg_free_processor_mod((struct ofl_msg_processor_mod *)msg, errbuf);; } case OFPT_PROCESSOR_CTRL: { return ofl_msg_free_processor_ctrl((struct ofl_msg_processor_ctrl *)msg, errbuf);; } case OFPT_STATS_REQUEST: { return ofl_msg_free_stats_request((struct ofl_msg_stats_request_header *)msg, exp, errbuf); } case OFPT_STATS_REPLY: { return ofl_msg_free_stats_reply((struct ofl_msg_stats_reply_header *)msg, exp, errbuf); } case OFPT_BARRIER_REQUEST: case OFPT_BARRIER_REPLY: case OFPT_QUEUE_GET_CONFIG_REQUEST: { break; } case OFPT_QUEUE_GET_CONFIG_REPLY: { struct ofl_msg_queue_get_config_reply *mod = (struct ofl_msg_queue_get_config_reply *)msg; OFL_UTILS_FREE_ARR_FUN(mod->queues, mod->queues_num, ofl_structs_free_packet_queue); break; } } free(msg); return 0; }
ofl_err pipeline_handle_flow_mod(struct pipeline *pl, struct ofl_msg_flow_mod *msg, const struct sender *sender) { /* Note: the result of using table_id = 0xff is undefined in the spec. * for now it is accepted for delete commands, meaning to delete * from all tables */ ofl_err error; size_t i; bool match_kept,insts_kept; if(sender->remote->role == OFPCR_ROLE_SLAVE) return ofl_error(OFPET_BAD_REQUEST, OFPBRC_IS_SLAVE); match_kept = false; insts_kept = false; // Validate actions in flow_mod for (i=0; i< msg->instructions_num; i++) { if (msg->instructions[i]->type == OFPIT_APPLY_ACTIONS || msg->instructions[i]->type == OFPIT_WRITE_ACTIONS) { struct ofl_instruction_actions *ia = (struct ofl_instruction_actions *)msg->instructions[i]; error = dp_actions_validate(pl->dp, ia->actions_num, ia->actions); if (error) { return error; } } } if (msg->table_id == 0xff) { if (msg->command == OFPFC_DELETE || msg->command == OFPFC_DELETE_STRICT) { size_t i; error = 0; for (i=0; i < PIPELINE_TABLES; i++) { error = flow_table_flow_mod(pl->tables[i], msg, &match_kept, &insts_kept); if (error) { break; } } if (error) { return error; } else { ofl_msg_free_flow_mod(msg, !match_kept, !insts_kept, pl->dp->exp); return 0; } } else { return ofl_error(OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_TABLE_ID); } } else { error = flow_table_flow_mod(pl->tables[msg->table_id], msg, &match_kept, &insts_kept); if (error) { return error; } if ((msg->command == OFPFC_ADD || msg->command == OFPFC_MODIFY || msg->command == OFPFC_MODIFY_STRICT) && msg->buffer_id != NO_BUFFER) { /* run buffered message through pipeline */ struct packet *pkt; pkt = dp_buffers_retrieve(pl->dp->buffers, msg->buffer_id); if (pkt != NULL) { pipeline_process_packet(pl, pkt); } else { VLOG_WARN_RL(LOG_MODULE, &rl, "The buffer flow_mod referred to was empty (%u).", msg->buffer_id); } } ofl_msg_free_flow_mod(msg, !match_kept, !insts_kept, pl->dp->exp); return 0; } }
int ofl_msg_free(struct ofl_msg_header *msg, struct ofl_exp *exp) { switch (msg->type) { case OFPT_HELLO: { break; } case OFPT_ERROR: { return ofl_msg_free_error((struct ofl_msg_error *)msg); } case OFPT_ECHO_REQUEST: case OFPT_ECHO_REPLY: { free(((struct ofl_msg_echo *)msg)->data); break; } case OFPT_EXPERIMENTER: { if (exp == NULL || exp->msg == NULL || exp->msg->free == NULL) { OFL_LOG_WARN(LOG_MODULE, "Trying to free EXPERIMENTER message, but no callback was given"); break; } exp->msg->free((struct ofl_msg_experimenter *)msg); return 0; } case OFPT_FEATURES_REQUEST: { break; } case OFPT_FEATURES_REPLY: { break; } case OFPT_GET_CONFIG_REQUEST: { break; } case OFPT_GET_CONFIG_REPLY: { free(((struct ofl_msg_get_config_reply *)msg)->config); break; } case OFPT_SET_CONFIG: { free(((struct ofl_msg_set_config *)msg)->config); break; } case OFPT_PACKET_IN: { ofl_structs_free_match(((struct ofl_msg_packet_in *)msg)->match,NULL); free(((struct ofl_msg_packet_in *)msg)->data); break; } case OFPT_FLOW_REMOVED: { return ofl_msg_free_flow_removed((struct ofl_msg_flow_removed *)msg, true, exp); break; } case OFPT_PORT_STATUS: { free(((struct ofl_msg_port_status *)msg)->desc); break; } case OFPT_PACKET_OUT: { return ofl_msg_free_packet_out((struct ofl_msg_packet_out *)msg, true, exp); } case OFPT_FLOW_MOD: { return ofl_msg_free_flow_mod((struct ofl_msg_flow_mod *)msg, true, true, exp); } case OFPT_GROUP_MOD: { return ofl_msg_free_group_mod((struct ofl_msg_group_mod *)msg, true, exp); } case OFPT_PORT_MOD: case OFPT_TABLE_MOD: { break; } case OFPT_MULTIPART_REQUEST: { return ofl_msg_free_multipart_request((struct ofl_msg_multipart_request_header *)msg, exp); } case OFPT_MULTIPART_REPLY: { return ofl_msg_free_multipart_reply((struct ofl_msg_multipart_reply_header *)msg, exp); } case OFPT_BARRIER_REQUEST: case OFPT_BARRIER_REPLY: case OFPT_QUEUE_GET_CONFIG_REQUEST: { break; } case OFPT_ROLE_REPLY: case OFPT_ROLE_REQUEST:{ break; } case OFPT_GET_ASYNC_REPLY: case OFPT_SET_ASYNC: case OFPT_GET_ASYNC_REQUEST:{ break; } case OFPT_METER_MOD:{ return ofl_msg_free_meter_mod((struct ofl_msg_meter_mod*)msg, true); } case OFPT_QUEUE_GET_CONFIG_REPLY: { struct ofl_msg_queue_get_config_reply *mod = (struct ofl_msg_queue_get_config_reply *)msg; OFL_UTILS_FREE_ARR_FUN(mod->queues, mod->queues_num, ofl_structs_free_packet_queue); break; } } free(msg); return 0; }