Beispiel #1
0
int
ofl_msg_free_group_mod(struct ofl_msg_group_mod *msg, bool with_buckets, struct ofl_exp *exp, char *errbuf) {
    if (with_buckets) {
        OFL_UTILS_FREE_ARR_FUN3(msg->buckets, msg->buckets_num,
                                ofl_structs_free_bucket, exp, errbuf);
    }

    free(msg);
    return 0;
}
Beispiel #2
0
int
ofl_msg_free_packet_out(struct ofl_msg_packet_out *msg, bool with_data, struct ofl_exp *exp, char *errbuf) {
    if (with_data) {
        free(msg->data);
    }
    OFL_UTILS_FREE_ARR_FUN3(msg->actions, msg->actions_num,
                            ofl_actions_free, exp, errbuf);
    //TODO err

    free(msg);
    return 0;
}
Beispiel #3
0
int
ofl_msg_free_flow_mod(struct ofl_msg_flow_mod *msg, bool with_match, bool with_instructions, struct ofl_exp *exp, char *errbuf) {
    if (with_match) {
        ofl_structs_free_match(msg->match, exp, errbuf);
        //TODO error
    }
    if (with_instructions) {
        OFL_UTILS_FREE_ARR_FUN3(msg->instructions, msg->instructions_num,
                                ofl_structs_free_instruction, exp, errbuf);
        //TODO error
    }

    free(msg);
    return 0;
}
Beispiel #4
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, char *errbuf) {
    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)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received group desc stats reply is too short (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    if (*len < ntohs(src->length)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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 (errbuf != NULL) {
            char *gs = ofl_group_to_string(ntohl(src->group_id));
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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, errbuf);
    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, errbuf);
        if (error) {
            OFL_UTILS_FREE_ARR_FUN3(dm->buckets, i,
                                    ofl_structs_free_bucket, exp, errbuf);
            free (dm);
            return error;
        }
        bucket = (struct ofp_bucket *)((uint8_t *)bucket + ntohs(bucket->len));
    }

    if (dlen != 0) {
        *len = *len - ntohs(src->length) + dlen;
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "The received group desc stats contained extra bytes (%zu).", dlen);
        }
        ofl_structs_free_group_desc_stats(dm, exp, NULL);
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    *len -= ntohs(src->length);
    *dst = dm;
    return 0;
}
Beispiel #5
0
ofl_err
ofl_structs_flow_stats_unpack(struct ofp_flow_stats *src, size_t *len, struct ofl_flow_stats **dst, struct ofl_exp *exp, char *errbuf) {
    struct ofl_flow_stats *s;
    struct ofp_instruction *inst;
    ofl_err error;
    size_t slen;
    size_t i;

    if (*len < (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match))) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received flow stats has invalid length (%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 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 == 0xff) {
        if (errbuf != NULL) {
            char *ts = ofl_table_to_string(src->table_id);
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received flow stats has invalid table_id (%s).", ts);
            free(ts);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }

    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);

    error = ofl_structs_match_unpack(&(src->match), &slen, &(s->match), exp, errbuf);
    if (error) {
        free(s);
        return error;
    }

    error = ofl_utils_count_ofp_instructions(src->instructions, slen, &s->instructions_num, errbuf);
    if (error) {
        ofl_structs_free_match(s->match, exp, NULL);
        free(s);
        return error;
    }
    s->instructions = (struct ofl_instruction_header **)malloc(s->instructions_num * sizeof(struct ofl_instruction_header *));

    inst = src->instructions;
    for (i = 0; i < s->instructions_num; i++) {
        error = ofl_structs_instructions_unpack(inst, &slen, &(s->instructions[i]), exp, errbuf);
        if (error) {
            OFL_UTILS_FREE_ARR_FUN3(s->instructions, i,
                                    ofl_structs_free_instruction, exp, errbuf);
            free(s);
            return error;
        }
        inst = (struct ofp_instruction *)((uint8_t *)inst + ntohs(inst->len));
    }

    if (slen != 0) {
        *len = *len - ntohs(src->length) + slen;
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "The received flow stats contained extra bytes (%zu).", slen);
        }
        ofl_structs_free_flow_stats(s, exp, errbuf);
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    *len -= ntohs(src->length);
    *dst = s;
    return 0;
}
Beispiel #6
0
ofl_err
ofl_structs_instructions_unpack(struct ofp_instruction *src, size_t *len, struct ofl_instruction_header **dst, struct ofl_exp *exp, char *errbuf) {
    size_t ilen;
    struct ofl_instruction_header *inst = NULL;

    if (*len < sizeof(struct ofp_instruction)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received instruction is too short (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
    }

    if (*len < ntohs(src->len)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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)) {
                if (errbuf != NULL) {
                    snprintf(errbuf, OFL_ERRBUF_SIZE, "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 == 0xff) {
                if (errbuf != NULL) {
                    char *ts = ofl_table_to_string(si->table_id);
                    snprintf(errbuf, OFL_ERRBUF_SIZE, "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)) {
                if (errbuf != NULL) {
                    snprintf(errbuf, OFL_ERRBUF_SIZE, "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 =      si->metadata;
            di->metadata_mask = 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)) {
                if (errbuf != NULL) {
                    snprintf(errbuf, OFL_ERRBUF_SIZE, "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, errbuf);
            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, errbuf);
                if (error) {
                    *len = *len - ntohs(src->len) + ilen;
                    OFL_UTILS_FREE_ARR_FUN3(di->actions, i,
                                            ofl_actions_free, exp, errbuf);
                    //TODO error
                    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)) {
                if (errbuf != NULL) {
                    snprintf(errbuf, OFL_ERRBUF_SIZE, "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_EXPERIMENTER: {
            ofl_err error;

            if (exp == NULL || exp->inst == NULL || exp->inst->unpack == NULL) {
                if (errbuf != NULL) {
                    snprintf(errbuf, OFL_ERRBUF_SIZE, "Received EXPERIMENTER instruction, but no callback was given.");
                }
                return ofl_error(OFPET_BAD_INSTRUCTION, OFPBIC_UNSUP_EXP_INST);
            }
            error = exp->inst->unpack(src, &ilen, &inst);
            if (error) {
                return error;
            }
            break;
        }
    }

    // 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;
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "The received instruction contained extra bytes (%zu).", ilen);
        }
        ofl_structs_free_instruction(inst, exp, errbuf);
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    *len -= ntohs(src->len);
    (*dst) = inst;

    return 0;
}
Beispiel #7
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, char *errbuf) {
    struct ofl_bucket *b;
    struct ofp_action_header *act;
    size_t blen;
    ofl_err error;
    size_t i;

    if (*len < sizeof(struct ofp_bucket)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received bucket is too short (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
    }

    if (*len < ntohs(src->len)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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, errbuf);
    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, errbuf);
        if (error) {
            *len = *len - ntohs(src->len) + blen;
            OFL_UTILS_FREE_ARR_FUN3(b->actions, i,
                                    ofl_actions_free, exp, errbuf);
            //TODO error
            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, errbuf);
        //TODO error
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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;
}
Beispiel #8
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;
}
Beispiel #9
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, char *errbuf) {
    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)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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 */) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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 (errbuf != NULL) {
            char *gs = ofl_group_to_string(ntohl(sm->group_id));
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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, errbuf);
    if (error) {
        free(dm);
        return error;
    }

    if (dm->command == OFPGC_DELETE && dm->buckets_num > 0) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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, errbuf);
        if (error) {
            OFL_UTILS_FREE_ARR_FUN3(dm->buckets, i,
                                    ofl_structs_free_bucket, exp, errbuf);
            free(dm);
            return error;
        }
        bucket = (struct ofp_bucket *)((uint8_t *)bucket + ntohs(bucket->len));
    }

    *msg = (struct ofl_msg_header *)dm;
    return 0;
}
Beispiel #10
0
static ofl_err
ofl_msg_unpack_flow_mod(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp, char *errbuf) {
    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))) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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, errbuf);
    if (error) {
        free(dm);
        return error;
    }

    error = ofl_utils_count_ofp_instructions(&(sm->instructions), *len, &dm->instructions_num, errbuf);
    if (error) {
        ofl_structs_free_match(dm->match, exp, NULL);
        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, errbuf);
        if (error) {
            OFL_UTILS_FREE_ARR_FUN3(dm->instructions, i,
                    ofl_structs_free_instruction, exp, errbuf);
            ofl_structs_free_match(dm->match, exp, NULL);
            free(dm);
            return error;
        }
        inst = (struct ofp_instruction *)((uint8_t *)inst + ntohs(inst->len));
    }

    *msg = (struct ofl_msg_header *)dm;
    return 0;
}
Beispiel #11
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, char *errbuf) {
    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)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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 (errbuf != NULL) {
            char *ps = ofl_port_to_string(ntohl(sp->in_port));
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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 (errbuf != NULL) {
            char *bs = ofl_buffer_to_string(ntohl(sp->buffer_id));
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "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, errbuf);
    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, errbuf);
        if (error) {
            OFL_UTILS_FREE_ARR_FUN3(dp->actions, i,
                                    ofl_actions_free, exp, errbuf);
            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;
}