ofl_err ofl_structs_meter_stats_unpack(struct ofp_meter_stats *src, size_t *len, struct ofl_meter_stats **dst) { struct ofl_meter_stats *s; struct ofp_meter_band_stats *c; ofl_err error; size_t slen; size_t i; if (*len < sizeof(struct ofp_meter_stats)) { OFL_LOG_WARN(LOG_MODULE, "Received meter stats reply is too short (%zu).", *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (*len < ntohs(src->len)) { OFL_LOG_WARN(LOG_MODULE, "Received meter stats reply has invalid length (set to %u, but only %zu received).", ntohs(src->len), *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } slen = ntohs(src->len) - sizeof(struct ofp_meter_stats); s = (struct ofl_meter_stats *) malloc(sizeof(struct ofl_meter_stats)); s->meter_id = ntohl(src->meter_id); s->len = ntohs(src->len); s->flow_count = ntohl(src->flow_count); s->packet_in_count = ntoh64(src->packet_in_count); s->byte_in_count = ntoh64(src->byte_in_count); s->duration_sec = htonl(src->duration_sec); s->duration_nsec = htonl(src->duration_nsec); error = ofl_utils_count_ofp_meter_band_stats(src->band_stats, slen, &s->meter_bands_num); if (error) { free(s); return error; } s->band_stats = (struct ofl_meter_band_stats **)malloc(s->meter_bands_num * sizeof(struct ofl_meter_band_stats *)); c = src->band_stats; for (i = 0; i < s->meter_bands_num; i++) { error = ofl_structs_meter_band_stats_unpack(c, &slen, &(s->band_stats[i])); if (error) { OFL_UTILS_FREE_ARR(s->band_stats, i); free(s); return error; } c = (struct ofp_meter_band_stats *)((uint8_t *)c + sizeof(struct ofp_meter_band_stats)); } if (slen != 0) { *len = *len - ntohs(src->len) + slen; OFL_LOG_WARN(LOG_MODULE, "The received meter stats contained extra bytes (%zu).", slen); ofl_structs_free_meter_stats(s); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->len); *dst = s; return 0; }
ofl_err ofl_structs_meter_config_unpack(struct ofp_meter_config *src, size_t *len, struct ofl_meter_config **dst) { struct ofl_meter_config *s; struct ofp_meter_band_header *b; ofl_err error; size_t slen; size_t i; if (*len < sizeof(struct ofp_meter_config)) { OFL_LOG_WARN(LOG_MODULE, "Received meter config reply is too short (%zu).", *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (*len < ntohs(src->length)) { OFL_LOG_WARN(LOG_MODULE, "Received meter config reply has invalid length (set to %u, but only %zu received).", ntohs(src->length), *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } slen = ntohs(src->length) - sizeof(struct ofp_meter_config); s = (struct ofl_meter_config *) malloc(sizeof(struct ofl_meter_config)); s->meter_id = ntohl(src->meter_id); s->length = ntohs(src->length); s->flags = ntohs(src->flags); error = ofl_utils_count_ofp_meter_bands(src->bands, slen, &s->meter_bands_num); if (error) { free(s); return error; } s->bands = (struct ofl_meter_band_header **)malloc(s->meter_bands_num * sizeof(struct ofl_meter_band_header *)); b= src->bands; for (i = 0; i < s->meter_bands_num; i++) { error = ofl_structs_meter_band_unpack(b, &slen, &(s->bands[i])); if (error) { OFL_UTILS_FREE_ARR(s->bands, i); free(s); return error; } b = (struct ofp_meter_band_header *)((uint8_t *)b + ntohs(b->len)); } if (slen != 0) { *len = *len - ntohs(src->length) + slen; OFL_LOG_WARN(LOG_MODULE, "The received meter config contained extra bytes (%zu).", slen); //ofl_structs_free_meter_stats(s); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->length); *dst = s; return 0; }
void meter_entry_destroy(struct meter_entry *entry) { struct flow_ref_entry *ref, *next; // remove all referencing flows LIST_FOR_EACH_SAFE(ref, next, struct flow_ref_entry, node, &entry->flow_refs) { flow_entry_remove(ref->entry, OFPRR_METER_DELETE);// METER_DELETE ??????? // Note: the flow_ref_entryf will be destroyed after a chain of calls in flow_entry_remove } OFL_UTILS_FREE_ARR_FUN(entry->config->bands, entry->config->meter_bands_num, ofl_structs_free_meter_bands); free(entry->config); OFL_UTILS_FREE_ARR(entry->stats->band_stats, entry->stats->meter_bands_num); free(entry->stats); free(entry); }
static ofl_err ofl_msg_unpack_features_reply(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, char *errbuf) { struct ofp_switch_features *sr; struct ofl_msg_features_reply *dr; struct ofp_port *port; ofl_err error = 0; size_t i; if (*len < sizeof(struct ofp_switch_features)) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Received FEATURES_REPLY message has invalid length (%zu).", *len); } return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= sizeof(struct ofp_switch_features); sr = (struct ofp_switch_features *)src; dr = (struct ofl_msg_features_reply *)malloc(sizeof(struct ofl_msg_features_reply)); dr->datapath_id = ntoh64(sr->datapath_id); dr->n_buffers = ntohl( sr->n_buffers); dr->n_tables = ntohl( sr->n_tables); dr->capabilities = ntohl( sr->capabilities); error = ofl_utils_count_ofp_ports(&(sr->ports), *len, &dr->ports_num); if (error) { free(dr); return error; } dr->ports = (struct ofl_port **)malloc(dr->ports_num * sizeof(struct ofl_port *)); port = sr->ports; for (i = 0; i < dr->ports_num; i++) { error = ofl_structs_port_unpack(port, len, &(dr->ports[i]), errbuf); if (error) { OFL_UTILS_FREE_ARR(dr->ports, i); free(dr); return error; } port = (struct ofp_port *)((uint8_t *)port + sizeof(struct ofp_port)); } *msg = (struct ofl_msg_header *)dr; return 0; }
ofl_err ofl_structs_group_stats_unpack(struct ofp_group_stats *src, size_t *len, struct ofl_group_stats **dst, char *errbuf) { struct ofl_group_stats *s; struct ofp_bucket_counter *c; ofl_err error; size_t slen; size_t i; if (*len < sizeof(struct ofp_group_stats)) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Received group desc stats reply is too short (%zu).", *len); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } if (*len < ntohs(src->length)) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Received group stats reply has invalid length (set to %u, but only %zu received).", ntohs(src->length), *len); } return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (ntohl(src->group_id) > OFPG_MAX) { if (errbuf != NULL) { char *gs = ofl_group_to_string(ntohl(src->group_id)); snprintf(errbuf, OFL_ERRBUF_SIZE, "Received group stats has invalid group_id (%s).", gs); free(gs); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } slen = ntohs(src->length) - sizeof(struct ofp_group_stats); s = (struct ofl_group_stats *)malloc(sizeof(struct ofl_group_stats)); s->group_id = ntohl(src->group_id); s->ref_count = ntohl(src->ref_count); s->packet_count = ntoh64(src->packet_count); s->byte_count = ntoh64(src->byte_count); error = ofl_utils_count_ofp_bucket_counters(src->bucket_stats, slen, &s->counters_num); if (error) { free(s); return error; } s->counters = (struct ofl_bucket_counter **)malloc(s->counters_num * sizeof(struct ofl_bucket_counter *)); c = src->bucket_stats; for (i = 0; i < s->counters_num; i++) { error = ofl_structs_bucket_counter_unpack(c, &slen, &(s->counters[i]), errbuf); if (error) { OFL_UTILS_FREE_ARR(s->counters, i); free(s); return error; } c = (struct ofp_bucket_counter *)((uint8_t *)c + sizeof(struct ofp_bucket_counter)); } if (slen != 0) { *len = *len - ntohs(src->length) + slen; if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "The received group stats contained extra bytes (%zu).", slen); } ofl_structs_free_group_stats(s); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->length); *dst = s; return 0; }
/* Frees the OFlib stats reply message along with any dynamically allocated * structures. */ static int ofl_msg_free_stats_reply(struct ofl_msg_stats_reply_header *msg, struct ofl_exp *exp, char *errbuf) { switch (msg->type) { case OFPST_DESC: { struct ofl_msg_stats_reply_desc *stat = (struct ofl_msg_stats_reply_desc *)msg; free(stat->mfr_desc); free(stat->hw_desc); free(stat->sw_desc); free(stat->serial_num); free(stat->dp_desc); break; } case OFPST_FLOW: { struct ofl_msg_stats_reply_flow *stat = (struct ofl_msg_stats_reply_flow *)msg; OFL_UTILS_FREE_ARR_FUN3(stat->stats, stat->stats_num, ofl_structs_free_flow_stats, exp, errbuf); //TODO error break; } case OFPST_AGGREGATE: { break; } case OFPST_TABLE: { struct ofl_msg_stats_reply_table *stat = (struct ofl_msg_stats_reply_table *)msg; OFL_UTILS_FREE_ARR_FUN(stat->stats, stat->stats_num, ofl_structs_free_table_stats); break; } case OFPST_PORT: { struct ofl_msg_stats_reply_port *stat = (struct ofl_msg_stats_reply_port *)msg; OFL_UTILS_FREE_ARR(stat->stats, stat->stats_num); break; } case OFPST_QUEUE: { struct ofl_msg_stats_reply_queue *stat = (struct ofl_msg_stats_reply_queue *)msg; OFL_UTILS_FREE_ARR(stat->stats, stat->stats_num); break; } case OFPST_GROUP: { struct ofl_msg_stats_reply_group *stat = (struct ofl_msg_stats_reply_group *)msg; OFL_UTILS_FREE_ARR_FUN(stat->stats, stat->stats_num, ofl_structs_free_group_stats); break; } case OFPST_GROUP_DESC: { struct ofl_msg_stats_reply_group_desc *stat = (struct ofl_msg_stats_reply_group_desc *)msg; OFL_UTILS_FREE_ARR_FUN3(stat->stats, stat->stats_num, ofl_structs_free_group_desc_stats, exp, errbuf); //TODO error break; } case OFPST_EXPERIMENTER: { if (exp == NULL || exp->stats || exp->stats->reply_free == NULL) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Trying to free EXPERIMENTER stats reply, but no callback was given."); } free(msg); return -1; } exp->stats->reply_free(msg); return 0; } default: { return -1; } } free(msg); return 0; }
/* Frees the OFlib stats reply message along with any dynamically allocated * structures. */ static int ofl_msg_free_multipart_reply(struct ofl_msg_multipart_reply_header *msg, struct ofl_exp *exp) { switch (msg->type) { case OFPMP_DESC: { struct ofl_msg_reply_desc *stat = (struct ofl_msg_reply_desc *) msg; free(stat->mfr_desc); free(stat->hw_desc); free(stat->sw_desc); free(stat->serial_num); free(stat->dp_desc); break; } case OFPMP_FLOW: { struct ofl_msg_multipart_reply_flow *stat = (struct ofl_msg_multipart_reply_flow *)msg; OFL_UTILS_FREE_ARR_FUN2(stat->stats, stat->stats_num, ofl_structs_free_flow_stats, exp); } case OFPMP_AGGREGATE: { break; } case OFPMP_TABLE: { struct ofl_msg_multipart_reply_table *stat = (struct ofl_msg_multipart_reply_table *)msg; OFL_UTILS_FREE_ARR_FUN(stat->stats, stat->stats_num, ofl_structs_free_table_stats); break; } case OFPMP_PORT_STATS: { struct ofl_msg_multipart_reply_port *stat = (struct ofl_msg_multipart_reply_port *)msg; OFL_UTILS_FREE_ARR(stat->stats, stat->stats_num); break; } case OFPMP_QUEUE: { struct ofl_msg_multipart_reply_queue *stat = (struct ofl_msg_multipart_reply_queue *)msg; OFL_UTILS_FREE_ARR(stat->stats, stat->stats_num); break; } case OFPMP_GROUP: { struct ofl_msg_multipart_reply_group *stat = (struct ofl_msg_multipart_reply_group *)msg; OFL_UTILS_FREE_ARR_FUN(stat->stats, stat->stats_num, ofl_structs_free_group_stats); break; } case OFPMP_METER:{ struct ofl_msg_multipart_reply_meter *stat = (struct ofl_msg_multipart_reply_meter*)msg; OFL_UTILS_FREE_ARR_FUN(stat->stats, stat->stats_num, ofl_structs_free_meter_stats); break; } case OFPMP_METER_CONFIG:{ struct ofl_msg_multipart_reply_meter_conf *conf = (struct ofl_msg_multipart_reply_meter_conf *)msg; OFL_UTILS_FREE_ARR_FUN(conf->stats, conf->stats_num, ofl_structs_free_meter_config); break; } case OFPMP_METER_FEATURES:{ struct ofl_msg_multipart_reply_meter_features *feat = (struct ofl_msg_multipart_reply_meter_features *)msg; free(feat->features); break; } case OFPMP_GROUP_DESC: { struct ofl_msg_multipart_reply_group_desc *stat = (struct ofl_msg_multipart_reply_group_desc *)msg; OFL_UTILS_FREE_ARR_FUN2(stat->stats, stat->stats_num, ofl_structs_free_group_desc_stats, exp); break; } case OFPMP_PORT_DESC:{ struct ofl_msg_multipart_reply_port_desc *stat = (struct ofl_msg_multipart_reply_port_desc *)msg; OFL_UTILS_FREE_ARR_FUN(stat->stats, stat->stats_num, ofl_structs_free_port); break; } case OFPMP_TABLE_FEATURES:{ struct ofl_msg_multipart_reply_table_features *m = (struct ofl_msg_multipart_reply_table_features *)msg; OFL_UTILS_FREE_ARR_FUN2(m->table_features, m->tables_num, ofl_structs_free_table_features, exp); break; } case OFPMP_EXPERIMENTER: { if (exp == NULL || exp->stats || exp->stats->reply_free == NULL) { OFL_LOG_WARN(LOG_MODULE, "Trying to free EXPERIMENTER stats reply, but no callback was given."); break; } exp->stats->reply_free(msg); return 0; } case OFPMP_GROUP_FEATURES:{ break; } default: { return -1; } } free(msg); return 0; }