static ofl_err ofl_msg_unpack_flow_mod(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp) { struct ofp_flow_mod *sm; struct ofl_msg_flow_mod *dm; struct ofp_instruction *inst; ofl_err error; size_t i; if (*len < (sizeof(struct ofp_flow_mod) - sizeof(struct ofp_match))) { OFL_LOG_WARN(LOG_MODULE, "Received FLOW_MOD message has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } *len -= (sizeof(struct ofp_flow_mod) - sizeof(struct ofp_match)); sm = (struct ofp_flow_mod *)src; dm = (struct ofl_msg_flow_mod *)malloc(sizeof(struct ofl_msg_flow_mod)); dm->cookie = ntoh64(sm->cookie); dm->cookie_mask = ntoh64(sm->cookie_mask); dm->table_id = sm->table_id; dm->command = (enum ofp_flow_mod_command)sm->command; dm->idle_timeout = ntohs( sm->idle_timeout); dm->hard_timeout = ntohs( sm->hard_timeout); dm->priority = ntohs( sm->priority); dm->buffer_id = ntohl( sm->buffer_id); dm->out_port = ntohl( sm->out_port); dm->out_group = ntohl( sm->out_group); dm->flags = ntohs( sm->flags); error = ofl_structs_match_unpack(&(sm->match), len, &(dm->match), exp); if (error) { free(dm); return error; } error = ofl_utils_count_ofp_instructions(&(sm->instructions), *len, &dm->instructions_num); if (error) { ofl_structs_free_match(dm->match, exp); free(dm); return error; } dm->instructions = (struct ofl_instruction_header **)malloc(dm->instructions_num * sizeof(struct ofl_instruction_header *)); inst = sm->instructions; for (i = 0; i < dm->instructions_num; i++) { error = ofl_structs_instructions_unpack(inst, len, &(dm->instructions[i]), exp); if (error) { OFL_UTILS_FREE_ARR_FUN2(dm->instructions, i, ofl_structs_free_instruction, exp); ofl_structs_free_match(dm->match, exp); free(dm); return error; } inst = (struct ofp_instruction *)((uint8_t *)inst + ntohs(inst->len)); } *msg = (struct ofl_msg_header *)dm; return 0; }
int ofl_msg_free_group_mod(struct ofl_msg_group_mod *msg, bool with_buckets, struct ofl_exp *exp) { if (with_buckets) { OFL_UTILS_FREE_ARR_FUN2(msg->buckets, msg->buckets_num, ofl_structs_free_bucket, exp); } free(msg); return 0; }
int ofl_msg_free_packet_out(struct ofl_msg_packet_out *msg, bool with_data, struct ofl_exp *exp) { if (with_data) { free(msg->data); } OFL_UTILS_FREE_ARR_FUN2(msg->actions, msg->actions_num, ofl_actions_free, exp); free(msg); return 0; }
int ofl_msg_free_flow_mod(struct ofl_msg_flow_mod *msg, bool with_match, bool with_instructions, struct ofl_exp *exp) { if (with_match) { ofl_structs_free_match(msg->match, exp); } if (with_instructions) { OFL_UTILS_FREE_ARR_FUN2(msg->instructions, msg->instructions_num, ofl_structs_free_instruction, exp); } free(msg); return 0; }
void flow_entry_replace_instructions(struct flow_entry *entry, size_t instructions_num, struct ofl_instruction_header **instructions) { /* TODO Zoltan: could be done more efficiently, but... */ del_group_refs(entry); OFL_UTILS_FREE_ARR_FUN2(entry->stats->instructions, entry->stats->instructions_num, ofl_structs_free_instruction, entry->dp->exp); entry->stats->instructions_num = instructions_num; entry->stats->instructions = instructions; init_group_refs(entry); }
static int ofl_msg_free_multipart_request(struct ofl_msg_multipart_request_header *msg, struct ofl_exp *exp) { switch (msg->type) { case OFPMP_DESC: { break; } case OFPMP_FLOW: case OFPMP_AGGREGATE: { ofl_structs_free_match(((struct ofl_msg_multipart_request_flow *)msg)->match, exp); break; } case OFPMP_TABLE: case OFPMP_PORT_STATS : case OFPMP_QUEUE: case OFPMP_GROUP: case OFPMP_GROUP_DESC: case OFPMP_GROUP_FEATURES: case OFPMP_METER: case OFPMP_METER_CONFIG: case OFPMP_METER_FEATURES: break; case OFPMP_TABLE_FEATURES:{ struct ofl_msg_multipart_request_table_features *m = (struct ofl_msg_multipart_request_table_features *)msg; OFL_UTILS_FREE_ARR_FUN2(m->table_features, m->tables_num, ofl_structs_free_table_features, exp); break; } case OFPMP_PORT_DESC: break; case OFPMP_EXPERIMENTER: { if (exp == NULL || exp->stats == NULL || exp->stats->req_free == NULL) { OFL_LOG_WARN(LOG_MODULE, "Trying to free EXPERIMENTER stats request, but no callback was given."); break; } exp->stats->req_free(msg); return 0; } default: return -1; } free(msg); return 0; }
ofl_err ofl_structs_instructions_unpack(struct ofp_instruction *src, size_t *len, struct ofl_instruction_header **dst, struct ofl_exp *exp) { size_t ilen; struct ofl_instruction_header *inst = NULL; if (*len < sizeof(struct ofp_instruction)) { OFL_LOG_WARN(LOG_MODULE, "Received instruction is too short (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } if (*len < ntohs(src->len)) { OFL_LOG_WARN(LOG_MODULE, "Received instruction has invalid length (set to %u, but only %zu received).", ntohs(src->len), *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } ilen = ntohs(src->len); switch (ntohs(src->type)) { case OFPIT_GOTO_TABLE: { struct ofp_instruction_goto_table *si; struct ofl_instruction_goto_table *di; if (ilen < sizeof(struct ofp_instruction_goto_table)) { OFL_LOG_WARN(LOG_MODULE, "Received GOTO_TABLE instruction has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } si = (struct ofp_instruction_goto_table *)src; if (si->table_id >= PIPELINE_TABLES) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *ts = ofl_table_to_string(si->table_id); OFL_LOG_WARN(LOG_MODULE, "Received GOTO_TABLE instruction has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_INSTRUCTION, OFPBIC_BAD_TABLE_ID); } di = (struct ofl_instruction_goto_table *)malloc(sizeof(struct ofl_instruction_goto_table)); di->table_id = si->table_id; inst = (struct ofl_instruction_header *)di; ilen -= sizeof(struct ofp_instruction_goto_table); break; } case OFPIT_WRITE_METADATA: { struct ofp_instruction_write_metadata *si; struct ofl_instruction_write_metadata *di; if (ilen < sizeof(struct ofp_instruction_write_metadata)) { OFL_LOG_WARN(LOG_MODULE, "Received WRITE_METADATA instruction has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } si = (struct ofp_instruction_write_metadata *)src; di = (struct ofl_instruction_write_metadata *)malloc(sizeof(struct ofl_instruction_write_metadata)); di->metadata = ntoh64(si->metadata); di->metadata_mask = ntoh64(si->metadata_mask); inst = (struct ofl_instruction_header *)di; ilen -= sizeof(struct ofp_instruction_write_metadata); break; } case OFPIT_WRITE_ACTIONS: case OFPIT_APPLY_ACTIONS: { struct ofp_instruction_actions *si; struct ofl_instruction_actions *di; struct ofp_action_header *act; ofl_err error; size_t i; if (ilen < sizeof(struct ofp_instruction_actions)) { OFL_LOG_WARN(LOG_MODULE, "Received *_ACTIONS instruction has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } ilen -= sizeof(struct ofp_instruction_actions); si = (struct ofp_instruction_actions *)src; di = (struct ofl_instruction_actions *)malloc(sizeof(struct ofl_instruction_actions)); error = ofl_utils_count_ofp_actions((uint8_t *)si->actions, ilen, &di->actions_num); if (error) { free(di); return error; } di->actions = (struct ofl_action_header **)malloc(di->actions_num * sizeof(struct ofl_action_header *)); act = si->actions; for (i = 0; i < di->actions_num; i++) { error = ofl_actions_unpack(act, &ilen, &(di->actions[i]), exp); if (error) { *len = *len - ntohs(src->len) + ilen; OFL_UTILS_FREE_ARR_FUN2(di->actions, i, ofl_actions_free, exp); free(di); return error; } act = (struct ofp_action_header *)((uint8_t *)act + ntohs(act->len)); } inst = (struct ofl_instruction_header *)di; break; } case OFPIT_CLEAR_ACTIONS: { if (ilen < sizeof(struct ofp_instruction_actions)) { OFL_LOG_WARN(LOG_MODULE, "Received CLEAR_ACTIONS instruction has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } inst = (struct ofl_instruction_header *)malloc(sizeof(struct ofl_instruction_header)); inst->type = (enum ofp_instruction_type)ntohs(src->type); ilen -= sizeof(struct ofp_instruction_actions); break; } case OFPIT_METER: { struct ofp_instruction_meter *si; struct ofl_instruction_meter *di; if (ilen < sizeof(struct ofp_instruction_meter)) { OFL_LOG_WARN(LOG_MODULE, "Received METER instruction has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } si = (struct ofp_instruction_meter*)src; di = (struct ofl_instruction_meter *)malloc(sizeof(struct ofl_instruction_meter)); di->meter_id = ntohl(si->meter_id); inst = (struct ofl_instruction_header *)di; ilen -= sizeof(struct ofp_instruction_meter); break; } case OFPIT_EXPERIMENTER: { ofl_err error; if (exp == NULL || exp->inst == NULL || exp->inst->unpack == NULL) { OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER instruction, but no callback was given."); return ofl_error(OFPET_BAD_INSTRUCTION, OFPBIC_UNSUP_INST); } error = exp->inst->unpack(src, &ilen, &inst); if (error) { return error; } break; } default: OFL_LOG_WARN(LOG_MODULE, "The received instruction type (%u) is invalid.", ntohs(src->type)); return ofl_error(OFPET_BAD_INSTRUCTION, OFPBIC_UNKNOWN_INST); } // must set type before check, so free works correctly inst->type = (enum ofp_instruction_type)ntohs(src->type); if (ilen != 0) { *len = *len - ntohs(src->len) + ilen; OFL_LOG_WARN(LOG_MODULE, "The received instruction contained extra bytes (%zu).", ilen); ofl_structs_free_instruction(inst, exp); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->len); (*dst) = inst; return 0; }
ofl_err ofl_structs_flow_stats_unpack(struct ofp_flow_stats *src, uint8_t *buf, size_t *len, struct ofl_flow_stats **dst, struct ofl_exp *exp) { struct ofl_flow_stats *s; struct ofp_instruction *inst; ofl_err error; size_t slen; size_t i; int match_pos; if (*len < ( (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match)) + ROUND_UP(ntohs(src->match.length),8))) { OFL_LOG_WARN(LOG_MODULE, "Received flow stats has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (*len < ntohs(src->length)) { OFL_LOG_WARN(LOG_MODULE, "Received flow 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 (src->table_id >= PIPELINE_TABLES) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *ts = ofl_table_to_string(src->table_id); OFL_LOG_WARN(LOG_MODULE, "Received flow stats has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_TABLE_ID); } slen = ntohs(src->length) - (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match)); s = (struct ofl_flow_stats *)malloc(sizeof(struct ofl_flow_stats)); s->table_id = src->table_id; s->duration_sec = ntohl( src->duration_sec); s->duration_nsec = ntohl( src->duration_nsec); s->priority = ntohs( src->priority); s->idle_timeout = ntohs( src->idle_timeout); s->hard_timeout = ntohs( src->hard_timeout); s->cookie = ntoh64(src->cookie); s->packet_count = ntoh64(src->packet_count); s->byte_count = ntoh64(src->byte_count); match_pos = sizeof(struct ofp_flow_stats) - 4; error = ofl_structs_match_unpack(&(src->match),buf + match_pos , &slen, &(s->match), exp); if (error) { free(s); return error; } error = ofl_utils_count_ofp_instructions((struct ofp_instruction *) (buf + ROUND_UP(match_pos + s->match->length,8)), slen, &s->instructions_num); if (error) { ofl_structs_free_match(s->match, exp); free(s); return error; } s->instructions = (struct ofl_instruction_header **)malloc(s->instructions_num * sizeof(struct ofl_instruction_header *)); inst = (struct ofp_instruction *) (buf + ROUND_UP(match_pos + s->match->length,8)); for (i = 0; i < s->instructions_num; i++) { error = ofl_structs_instructions_unpack(inst, &slen, &(s->instructions[i]), exp); if (error) { OFL_UTILS_FREE_ARR_FUN2(s->instructions, i, ofl_structs_free_instruction, exp); free(s); return error; } inst = (struct ofp_instruction *)((uint8_t *)inst + ntohs(inst->len)); } if (slen != 0) { *len = *len - ntohs(src->length) + slen; OFL_LOG_WARN(LOG_MODULE, "The received flow stats contained extra bytes (%zu).", slen); ofl_structs_free_flow_stats(s, exp); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->length); *dst = s; return 0; }
ofl_err ofl_structs_bucket_unpack(struct ofp_bucket *src, size_t *len, uint8_t gtype, struct ofl_bucket **dst, struct ofl_exp *exp) { struct ofl_bucket *b; struct ofp_action_header *act; size_t blen; ofl_err error; size_t i; if (*len < sizeof(struct ofp_bucket)) { OFL_LOG_WARN(LOG_MODULE, "Received bucket is too short (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } if (*len < ntohs(src->len)) { OFL_LOG_WARN(LOG_MODULE, "Received bucket has invalid length (set to %u, but only %zu received).", ntohs(src->len), *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } blen = ntohs(src->len) - sizeof(struct ofp_bucket); if (gtype == OFPGT_SELECT && ntohs(src->weight) == 0) { OFL_LOG_WARN(LOG_MODULE, "Received bucket has no weight for SELECT group."); return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_INVALID_GROUP); } if (gtype != OFPGT_SELECT && ntohs(src->weight) > 0) { OFL_LOG_WARN(LOG_MODULE, "Received bucket has weight for non-SELECT group."); return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_INVALID_GROUP); } b = (struct ofl_bucket *)malloc(sizeof(struct ofl_bucket)); b->weight = ntohs(src->weight); b->watch_port = ntohl(src->watch_port); b->watch_group = ntohl(src->watch_group); error = ofl_utils_count_ofp_actions((uint8_t *)src->actions, blen, &b->actions_num); if (error) { free(b); return error; } b->actions = (struct ofl_action_header **)malloc(b->actions_num * sizeof(struct ofl_action_header *)); act = src->actions; for (i = 0; i < b->actions_num; i++) { error = ofl_actions_unpack(act, &blen, &(b->actions[i]), exp); if (error) { *len = *len - ntohs(src->len) + blen; OFL_UTILS_FREE_ARR_FUN2(b->actions, i, ofl_actions_free, exp); free(b); return error; } act = (struct ofp_action_header *)((uint8_t *)act + ntohs(act->len)); } if (blen >= 8) { *len = *len - ntohs(src->len) + blen; ofl_structs_free_bucket(b, exp); OFL_LOG_WARN(LOG_MODULE, "Received bucket has more than 64 bit padding (%zu).", blen); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->len); *dst = b; return 0; }
ofl_err ofl_structs_group_desc_stats_unpack(struct ofp_group_desc_stats *src, size_t *len, struct ofl_group_desc_stats **dst, struct ofl_exp *exp) { struct ofl_group_desc_stats *dm; struct ofp_bucket *bucket; ofl_err error; size_t dlen; size_t i; if (*len < sizeof(struct ofp_group_desc_stats)) { OFL_LOG_WARN(LOG_MODULE, "Received group desc stats 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 group desc 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 (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *gs = ofl_group_to_string(ntohl(src->group_id)); OFL_LOG_WARN(LOG_MODULE, "Received group desc stats has invalid group_id (%s).", gs); free(gs); } return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } dlen = ntohs(src->length) - sizeof(struct ofp_group_desc_stats); dm = (struct ofl_group_desc_stats *)malloc(sizeof(struct ofl_group_desc_stats)); dm->type = src->type; dm->group_id = ntohl(src->group_id); error = ofl_utils_count_ofp_buckets(src->buckets, dlen, &dm->buckets_num); if (error) { free(dm); return error; } dm->buckets = (struct ofl_bucket **)malloc(dm->buckets_num * sizeof(struct ofl_bucket *)); bucket = src->buckets; for (i = 0; i < dm->buckets_num; i++) { error = ofl_structs_bucket_unpack(bucket, &dlen, dm->type, &(dm->buckets[i]), exp); if (error) { OFL_UTILS_FREE_ARR_FUN2(dm->buckets, i, ofl_structs_free_bucket, exp); free (dm); return error; } bucket = (struct ofp_bucket *)((uint8_t *)bucket + ntohs(bucket->len)); } if (dlen != 0) { *len = *len - ntohs(src->length) + dlen; OFL_LOG_WARN(LOG_MODULE, "The received group desc stats contained extra bytes (%zu).", dlen); ofl_structs_free_group_desc_stats(dm, exp); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->length); *dst = dm; return 0; }
static ofl_err ofl_msg_unpack_group_mod(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp) { struct ofp_group_mod *sm; struct ofl_msg_group_mod *dm; struct ofp_bucket *bucket; ofl_err error; size_t i; if (*len < sizeof(struct ofp_group_mod)) { OFL_LOG_WARN(LOG_MODULE, "Received GROUP_MOD message has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= sizeof(struct ofp_group_mod); sm = (struct ofp_group_mod *)src; if (ntohs(sm->command) > OFPGC_DELETE) { OFL_LOG_WARN(LOG_MODULE, "Received GROUP_MOD message with invalid command (%u).", ntohs(sm->command)); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); } if (ntohs(sm->type) > OFPGT_FF && ntohs(sm->type) < 128 /* experimenter */) { OFL_LOG_WARN(LOG_MODULE, "Received GROUP_MOD message with invalid type (%u).", ntohs(sm->type)); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); } if (ntohl(sm->group_id) > OFPG_MAX && !(ntohs(sm->command) == OFPGC_DELETE && ntohl(sm->group_id) == OFPG_ALL)) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *gs = ofl_group_to_string(ntohl(sm->group_id)); OFL_LOG_WARN(LOG_MODULE, "Received GROUP_MOD message with invalid group id (%s).", gs); free(gs); } return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_INVALID_GROUP); } dm = (struct ofl_msg_group_mod *)malloc(sizeof(struct ofl_msg_group_mod)); dm->command = (enum ofp_group_mod_command)ntohs(sm->command); dm->type = sm->type; dm->group_id = ntohl(sm->group_id); error = ofl_utils_count_ofp_buckets(&(sm->buckets), *len, &dm->buckets_num); if (error) { free(dm); return error; } if (dm->command == OFPGC_DELETE && dm->buckets_num > 0) { OFL_LOG_WARN(LOG_MODULE, "Received DELETE group command with buckets (%zu).", dm->buckets_num); free(dm); return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_INVALID_GROUP); } if (dm->type == OFPGT_INDIRECT && dm->buckets_num != 1) { OFL_LOG_WARN(LOG_MODULE, "Received INDIRECT group doesn't have exactly one bucket (%zu).", dm->buckets_num); free(dm); return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_INVALID_GROUP); } dm->buckets = (struct ofl_bucket **)malloc(dm->buckets_num * sizeof(struct ofl_bucket *)); bucket = sm->buckets; for (i = 0; i < dm->buckets_num; i++) { error = ofl_structs_bucket_unpack(bucket, len, dm->type, &(dm->buckets[i]), exp); if (error) { OFL_UTILS_FREE_ARR_FUN2(dm->buckets, i, ofl_structs_free_bucket, exp); free(dm); return error; } bucket = (struct ofp_bucket *)((uint8_t *)bucket + ntohs(bucket->len)); } *msg = (struct ofl_msg_header *)dm; return 0; }
static ofl_err ofl_msg_unpack_packet_out(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp) { struct ofp_packet_out *sp; struct ofl_msg_packet_out *dp; struct ofp_action_header *act; uint8_t *data; ofl_err error; size_t i, actions_num; if (*len < sizeof(struct ofp_packet_out)) { OFL_LOG_WARN(LOG_MODULE, "Received PACKET_OUT message has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } sp = (struct ofp_packet_out *)src; if (ntohl(sp->in_port) == 0 || (ntohl(sp->in_port) > OFPP_MAX && ntohl(sp->in_port) != OFPP_CONTROLLER)) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *ps = ofl_port_to_string(ntohl(sp->in_port)); OFL_LOG_WARN(LOG_MODULE, "Received PACKET_OUT message with invalid in_port (%s).", ps); free(ps); } return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); } if (ntohl(sp->buffer_id) != 0xffffffff && *len != sizeof(struct ofp_packet_out) + ntohs(sp->actions_len)) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *bs = ofl_buffer_to_string(ntohl(sp->buffer_id)); OFL_LOG_WARN(LOG_MODULE, "Received PACKET_OUT message with data and buffer_id (%s).", bs); free(bs); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } *len -= sizeof(struct ofp_packet_out); dp = (struct ofl_msg_packet_out *)malloc(sizeof(struct ofl_msg_packet_out)); dp->buffer_id = ntohl(sp->buffer_id); dp->in_port = ntohl(sp->in_port); if (*len < ntohs(sp->actions_len)) { OFL_LOG_WARN(LOG_MODULE, "Received PACKET_OUT message has invalid action length (%zu).", *len); free(dp); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } error = ofl_utils_count_ofp_actions(&(sp->actions), ntohs(sp->actions_len), &actions_num); if (error) { free(dp); return error; } dp->actions_num = actions_num; dp->actions = (struct ofl_action_header **)malloc(dp->actions_num * sizeof(struct ofp_action_header *)); // TODO Zoltan: Output actions can contain OFPP_TABLE act = sp->actions; for (i = 0; i < dp->actions_num; i++) { error = ofl_actions_unpack(act, len, &(dp->actions[i]), exp); if (error) { OFL_UTILS_FREE_ARR_FUN2(dp->actions, i, ofl_actions_free, exp); free(dp); } act = (struct ofp_action_header *)((uint8_t *)act + ntohs(act->len)); } data = ((uint8_t *)sp->actions) + ntohs(sp->actions_len); dp->data_length = *len; dp->data = *len > 0 ? (uint8_t *)memcpy(malloc(*len), data, *len) : NULL; *len = 0; *msg = (struct ofl_msg_header *)dp; 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; }