/* Handles meter_mod messages with ADD command. */ static ofl_err meter_table_add(struct meter_table *table, struct ofl_msg_meter_mod *mod) { struct meter_entry *entry; if (hmap_first_with_hash(&table->meter_entries, mod->meter_id) != NULL) { return ofl_error(OFPET_METER_MOD_FAILED, OFPMMFC_METER_EXISTS); } if (table->entries_num == DEFAULT_MAX_METER) { return ofl_error(OFPET_METER_MOD_FAILED, OFPMMFC_OUT_OF_METERS); } if (table->bands_num + mod->meter_bands_num > METER_TABLE_MAX_BANDS) { return ofl_error(OFPET_METER_MOD_FAILED, OFPMMFC_OUT_OF_BANDS); } entry = meter_entry_create(table->dp, table, mod); hmap_insert(&table->meter_entries, &entry->node, entry->stats->meter_id); table->entries_num++; table->bands_num += entry->stats->meter_bands_num; ofl_msg_free_meter_mod(mod, false); return 0; }
/* Handles meter_mod messages with MODIFY command. */ static ofl_err meter_table_modify(struct meter_table *table, struct ofl_msg_meter_mod *mod) { struct meter_entry *entry, *new_entry; entry = meter_table_find(table, mod->meter_id); if (entry == NULL) { return ofl_error(OFPET_METER_MOD_FAILED, OFPMMFC_UNKNOWN_METER); } if (table->bands_num - entry->config->meter_bands_num + mod->meter_bands_num > METER_TABLE_MAX_BANDS) { return ofl_error(OFPET_METER_MOD_FAILED, OFPMMFC_OUT_OF_BANDS); } new_entry = meter_entry_create(table->dp, table, mod); hmap_remove(&table->meter_entries, &entry->node); hmap_insert_fast(&table->meter_entries, &new_entry->node, mod->meter_id); table->bands_num = table->bands_num - entry->config->meter_bands_num + new_entry->stats->meter_bands_num; /* keep flow references from old meter entry */ list_replace(&new_entry->flow_refs, &entry->flow_refs); list_init(&entry->flow_refs); meter_entry_destroy(entry); ofl_msg_free_meter_mod(mod, false); return 0; }
/* Handles meter_mod messages with DELETE command. */ static ofl_err meter_table_delete(struct meter_table *table, struct ofl_msg_meter_mod *mod) { if (mod->meter_id == OFPM_ALL) { struct meter_entry *entry, *next; HMAP_FOR_EACH_SAFE(entry, next, struct meter_entry, node, &table->meter_entries) { meter_entry_destroy(entry); } hmap_destroy(&table->meter_entries); hmap_init(&table->meter_entries); table->entries_num = 0; table->bands_num = 0; ofl_msg_free_meter_mod(mod, false); return 0; } else {
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; }