/* ADD_MESSAGE message operation. */
static ofl_err
bundle_add_msg(struct bundle_table *table, struct ofl_msg_bundle_add_msg *add_msg) {
    struct bundle_table_entry *entry;
    struct bundle_message *new_message;
    ofl_err error = 0;

    entry = bundle_table_entry_find(table, add_msg->bundle_id);

    if (entry != NULL) {
        if (entry->flags != add_msg->flags) {
            error = ofl_error(OFPET_BUNDLE_FAILED, OFPBFC_BAD_FLAGS);
            bundle_table_entry_destroy(entry);
        } else if (entry->closed) {
            error = ofl_error(OFPET_BUNDLE_FAILED, OFPBFC_BUNDLE_CLOSED);
            bundle_table_entry_destroy(entry);
        }
    } else {
        entry = bundle_table_entry_create(add_msg->bundle_id, add_msg->flags);
        list_push_back(&table->bundle_table_entries, &entry->node);
    }

    if (!error) {
        new_message = bundle_message_create(add_msg);
        list_push_back(&entry->bundle_message_list, &new_message->node);
    }

    return error;
}
/* Close operation. */
static ofl_err
bundle_close(struct bundle_table *table,
             uint32_t bundle_id, uint16_t flags) {
    struct bundle_table_entry *entry;
    ofl_err error;

    entry = bundle_table_entry_find(table, bundle_id);
    if (entry == NULL) {
        error = ofl_error(OFPET_BUNDLE_FAILED, OFPBFC_BAD_ID);
    } else {
        if (entry->flags != flags) {
            error = ofl_error(OFPET_BUNDLE_FAILED, OFPBFC_BAD_FLAGS);
            bundle_table_entry_destroy(entry);
        } else if (entry->closed) {
            error = ofl_error(OFPET_BUNDLE_FAILED, OFPBFC_BUNDLE_CLOSED);
            bundle_table_entry_destroy(entry);
        } else {
            /* TODO check bundled messages (e.g. syntax / parameter check
             * and perform dry run of execution) to gain more confidence
             * that commit will succeed, return error if any issues found */

            /* Mark closed */
            entry->closed = true;
            error = 0;
        }
    }

    return error;
}
Beispiel #3
0
/* Handles group_mod messages with MODIFY command. */
static ofl_err
group_table_modify(struct group_table *table, struct ofl_msg_group_mod *mod) {
    struct group_entry *entry, *new_entry;

    entry = group_table_find(table, mod->group_id);
    if (entry == NULL) {
        return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_UNKNOWN_GROUP);
    }

    if (table->buckets_num - entry->desc->buckets_num + mod->buckets_num > GROUP_TABLE_MAX_BUCKETS) {
        return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_OUT_OF_BUCKETS);
    }

    if (!is_loop_free(table, entry)) {
        return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_LOOP);
    }

    new_entry = group_entry_create(table->dp, table, mod);

    hmap_remove(&table->entries, &entry->node);
    hmap_insert_fast(&table->entries, &new_entry->node, mod->group_id);

    table->buckets_num = table->buckets_num - entry->desc->buckets_num + new_entry->desc->buckets_num;
    group_entry_destroy(entry);

    ofl_msg_free_group_mod(mod, false, table->dp->exp);
    return 0;
}
Beispiel #4
0
ofl_err
ofl_exp_msg_unpack(struct ofp_header const *oh, size_t *len, struct ofl_msg_experimenter **msg, struct ofl_exp const * ofl_exp)
{
    struct ofp_experimenter_header *exp;

    if (*len < sizeof(struct ofp_experimenter_header)) {
        OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER message is shorter than ofp_experimenter_header.");
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    exp = (struct ofp_experimenter_header *)oh;

    switch (ntohl(exp->experimenter)) {
        case (OPENFLOW_VENDOR_ID): {
            return ofl_exp_openflow_msg_unpack(oh, len, msg);
        }
        case (NX_VENDOR_ID): {
            return ofl_exp_nicira_msg_unpack(oh, len, msg);
        }
        case (BEBA_VENDOR_ID): {
            return ofl_exp_beba_msg_unpack(oh, len, msg, ofl_exp);
        }
        default: {
            OFL_LOG_WARN(LOG_MODULE, "Trying to unpack unknown EXPERIMENTER message (%u).", ntohl(exp->experimenter));
            return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_EXPERIMENTER);
        }
    }
}
Beispiel #5
0
static ofl_err
ofl_msg_unpack_port_mod(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, char *errbuf) {
    struct ofp_port_mod *sm;
    struct ofl_msg_port_mod *dm;

    if (*len < sizeof(struct ofp_port_mod)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PORT_MOD has invalid length (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    sm = (struct ofp_port_mod *)src;

    if (ntohl(sm->port_no) == 0 || ntohl(sm->port_no) > OFPP_MAX) {
        if (errbuf != NULL) {
            char *ps = ofl_port_to_string(ntohl(sm->port_no));
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PORT_MOD message has invalid in_port (%s).", ps);
            free(ps);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
    }
    *len -= sizeof(struct ofp_port_mod);

    dm = (struct ofl_msg_port_mod *)malloc(sizeof(struct ofl_msg_port_mod));

    dm->port_no =   ntohl(sm->port_no);
    memcpy(dm->hw_addr, sm->hw_addr, OFP_ETH_ALEN);
    dm->config =    ntohl(sm->config);
    dm->mask =      ntohl(sm->mask);
    dm->advertise = ntohl(sm->advertise);

    *msg = (struct ofl_msg_header *)dm;
    return 0;
}
Beispiel #6
0
ofl_err
ofl_structs_queue_stats_unpack(struct ofp_queue_stats *src, size_t *len, struct ofl_queue_stats **dst, char *errbuf) {
    struct ofl_queue_stats *p;

    if (*len < sizeof(struct ofp_queue_stats)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received queue stats has invalid length (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    if (ntohl(src->port_no) == 0 || ntohl(src->port_no) > OFPP_MAX) {
        if (errbuf != NULL) {
            char *ps = ofl_port_to_string(ntohl(src->port_no));
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received queue stats has invalid port_id (%s).", ps);
            free(ps);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }
    *len -= sizeof(struct ofp_queue_stats);

    p = (struct ofl_queue_stats *)malloc(sizeof(struct ofl_queue_stats));

    p->port_no =    ntohl(src->port_no);
    p->queue_id =   ntohl(src->queue_id);
    p->tx_bytes =   ntoh64(src->tx_bytes);
    p->tx_packets = ntoh64(src->tx_packets);
    p->tx_errors =  ntoh64(src->tx_errors);

    *dst = p;
    return 0;
}
Beispiel #7
0
static ofl_err
ofl_msg_unpack_stats_request_queue(struct ofp_stats_request *os, size_t *len, struct ofl_msg_header **msg, char *errbuf) {
    struct ofp_queue_stats_request *sm;
    struct ofl_msg_stats_request_queue *dm;

    // ofp_stats_request length was checked at ofl_msg_unpack_stats_request

    if (*len < sizeof(struct ofp_queue_stats_request)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received QUEUE stats request has invalid length (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    sm = (struct ofp_queue_stats_request *)os->body;

    if (ntohl(sm->port_no) == 0 ||
        (ntohl(sm->port_no) > OFPP_MAX && ntohl(sm->port_no) != OFPP_ANY)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received QUEUE stats request has invalid port (%u).", ntohl(sm->port_no));
        }
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }
    *len -= sizeof(struct ofp_queue_stats_request);

    dm = (struct ofl_msg_stats_request_queue *)malloc(sizeof(struct ofl_msg_stats_request_queue));

    dm->port_no = ntohl(sm->port_no);
    dm->queue_id = ntohl(sm->queue_id);

    *msg = (struct ofl_msg_header *)dm;
    return 0;
}
ofl_err
ofl_structs_queue_stats_unpack(struct ofp_queue_stats *src, size_t *len, struct ofl_queue_stats **dst) {
    struct ofl_queue_stats *p;

    if (*len < sizeof(struct ofp_queue_stats)) {
        OFL_LOG_WARN(LOG_MODULE, "Received queue stats has invalid length (%zu).", *len);
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    if (ntohl(src->port_no) == 0 || ntohl(src->port_no) > OFPP_MAX) {
        if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) {
            char *ps = ofl_port_to_string(ntohl(src->port_no));
            OFL_LOG_WARN(LOG_MODULE, "Received queue stats has invalid port_id (%s).", ps);
            free(ps);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }
    *len -= sizeof(struct ofp_queue_stats);

    p = (struct ofl_queue_stats *)malloc(sizeof(struct ofl_queue_stats));

    p->port_no =    ntohl(src->port_no);
    p->queue_id =   ntohl(src->queue_id);
    p->tx_bytes =   ntoh64(src->tx_bytes);
    p->tx_packets = ntoh64(src->tx_packets);
    p->tx_errors =  ntoh64(src->tx_errors);
    p->duration_sec = ntohl(src->duration_sec);
    p->duration_nsec = ntohl(src->duration_nsec);
    *dst = p;
    return 0;
}
ofl_err
ofl_structs_table_stats_unpack(struct ofp_table_stats *src, size_t *len, struct ofl_table_stats **dst) {
    struct ofl_table_stats *p;

    if (*len < sizeof(struct ofp_table_stats)) {
        OFL_LOG_WARN(LOG_MODULE, "Received table stats has invalid length (%zu).", *len);
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }

    if (src->table_id == 0xff) {
        if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) {
            char *ts = ofl_table_to_string(src->table_id);
            OFL_LOG_WARN(LOG_MODULE, "Received table stats has invalid table_id (%s).", ts);
            free(ts);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }
    *len -= sizeof(struct ofp_table_stats);

    p = (struct ofl_table_stats *)malloc(sizeof(struct ofl_table_stats));
    p->table_id =      src->table_id;
    p->active_count =  ntohl(src->active_count);
    p->lookup_count =  ntoh64(src->lookup_count);
    p->matched_count = ntoh64(src->matched_count);

    *dst = p;
    return 0;
}
Beispiel #10
0
/* 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;
}
Beispiel #11
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;
}
static ofl_err
ofl_msg_unpack_stats_request_port(struct ofp_stats_request *os, size_t *len, struct ofl_msg_header **msg) {
    struct ofp_port_stats_request *sm;
    struct ofl_msg_stats_request_port *dm;

    // ofp_stats_request length was checked at ofl_msg_unpack_stats_request

    if (*len < sizeof(struct ofp_port_stats_request)) {
        OFL_LOG_WARN(LOG_MODULE, "Received PORT stats request has invalid length (%zu).", *len);
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    sm = (struct ofp_port_stats_request *)os->body;

    if (ntohl(sm->port_no) == 0 ||
        (ntohl(sm->port_no) > OFPP_MAX && ntohl(sm->port_no) != OFPP_ANY)) {
        OFL_LOG_WARN(LOG_MODULE, "Received PORT stats request has invalid port (%u).", ntohl(sm->port_no));
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    *len -= sizeof(struct ofp_port_stats_request);

    dm = (struct ofl_msg_stats_request_port *)malloc(sizeof(struct ofl_msg_stats_request_port));

    dm->port_no = ntohl(sm->port_no);

    *msg = (struct ofl_msg_header *)dm;
    return 0;
}
Beispiel #13
0
/* Handles group mod messages with ADD command. */
static ofl_err
group_table_add(struct group_table *table, struct ofl_msg_group_mod *mod) {

    struct group_entry *entry;

    if (hmap_first_with_hash(&table->entries, mod->group_id) != NULL) {
        return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_GROUP_EXISTS);
    }

    if (table->entries_num == GROUP_TABLE_MAX_ENTRIES) {
        return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_OUT_OF_GROUPS);
    }

    if (table->buckets_num + mod->buckets_num > GROUP_TABLE_MAX_BUCKETS) {
        return ofl_error(OFPET_GROUP_MOD_FAILED, OFPGMFC_OUT_OF_BUCKETS);
    }

    entry = group_entry_create(table->dp, table, mod);

    hmap_insert(&table->entries, &entry->node, entry->stats->group_id);

    table->entries_num++;
    table->buckets_num += entry->desc->buckets_num;

    ofl_msg_free_group_mod(mod, false, table->dp->exp);
    return 0;
}
Beispiel #14
0
ofl_err
ofl_exp_msg_unpack(struct ofp_header *oh, size_t *len, struct ofl_msg_experimenter **msg) {
    struct ofp_experimenter_header *exp;

    if (*len < sizeof(struct ofp_experimenter_header)) {
        OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER message is shorter than ofp_experimenter_header.");
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    exp = (struct ofp_experimenter_header *)oh;

    switch (htonl(exp->experimenter)) {
        case (OPENFLOW_VENDOR_ID): {
            return ofl_exp_openflow_msg_unpack(oh, len, msg);
        }
	/* Acrescentado pelo FRESDWN
        case (NX_VENDOR_ID): {
            return ofl_exp_nicira_msg_unpack(oh, len, msg);
        }
	 */
        case (NX_VENDOR_ID): {
            return ofl_exp_nicira_msg_unpack(oh, len, msg);
        }
        case (FRESDWN_VENDOR_ID): {
            return ofl_exp_fresdwn_msg_unpack(oh, len, msg);
        }
        default: {
            OFL_LOG_WARN(LOG_MODULE, "Trying to unpack unknown EXPERIMENTER message (%u).", htonl(exp->experimenter));
            return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_EXPERIMENTER);
        }
    }
}
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_table_features_unpack(struct ofp_table_features *src,size_t *len, struct ofl_table_features **dst, struct ofl_exp *exp){
    struct ofl_table_features *feat;
    uint8_t *prop;
    ofl_err error;
    size_t plen, i;
    
    if(*len < sizeof(struct ofp_table_features)){
        OFL_LOG_WARN(LOG_MODULE, "Received table feature is too short (%zu).", *len);  
        return ofl_error(OFPET_TABLE_FEATURES_FAILED, OFPTFFC_BAD_LEN);
    }
    
    if(*len < ntohs(src->length)){
        OFL_LOG_WARN(LOG_MODULE, "Received table_feature has invalid length (set to %u, but only %zu received).", ntohs(src->length), *len);
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
    }
    
    feat = (struct ofl_table_features*) malloc(sizeof(struct ofl_table_features));

    feat->length = ntohs(src->length);
    feat->table_id = src->table_id;
    feat->name = malloc(OFP_MAX_TABLE_NAME_LEN);
    strncpy(feat->name, src->name, OFP_MAX_TABLE_NAME_LEN);
    feat->metadata_match = ntoh64(src->metadata_match); 
    feat->metadata_write =  ntoh64(src->metadata_write);
    feat->config = ntohl(src->config);
    feat->max_entries = ntohl(src->max_entries);
    
    plen = ntohs(src->length) - sizeof(struct ofp_table_features);
    error = ofl_utils_count_ofp_table_features_properties((uint8_t*) src->properties, plen, &feat->properties_num);
    if (error) {
        free(feat);
        return error;
    }
    feat->properties = (struct ofl_table_feature_prop_header**) malloc(sizeof(struct ofl_table_feature_prop_header *) * feat->properties_num);
    
    prop = (uint8_t*) src->properties;
    for(i = 0; i < feat->properties_num; i++){
        error = ofl_structs_table_properties_unpack((struct ofp_table_feature_prop_header*) prop, &plen, &feat->properties[i], exp);
        if (error) {
            *len = *len - ntohs(src->length) + plen;
            /*OFL_UTILS_FREE_ARR_FUN2(b->actions, i,
                                    ofl_actions_free, exp);*/
            free(feat);
            return error;
        }
        prop += ROUND_UP(ntohs(((struct ofp_table_feature_prop_header*) prop)->length),8);
    }        
    
    *len -= ntohs(src->length);

    *dst = feat;
    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;
}
Beispiel #18
0
static ofl_err
ofl_msg_unpack_packet_in(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, char *errbuf) {
    struct ofp_packet_in *sp;
    struct ofl_msg_packet_in *dp;

    if (*len < sizeof(struct ofp_packet_in)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PACKET_IN message has invalid length (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }

    sp = (struct ofp_packet_in *)src;

    if (ntohl(sp->in_port) == 0 ||
        (ntohl(sp->in_port) > OFPP_MAX &&
         ntohl(sp->in_port) != OFPP_LOCAL)) {
        if (errbuf != NULL) {
            char *ps = ofl_port_to_string(ntohl(sp->in_port));
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PACKET_IN message has invalid in_port (%s).", ps);
            free(ps);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
    }

    if (sp->table_id == 0xff) {
        if (errbuf != NULL) {
            char *ts = ofl_table_to_string(sp->table_id);
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PACKET_IN has invalid table_id (%s).", ts);
            free(ts);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
    }
    *len -= sizeof(struct ofp_packet_in);

    dp = (struct ofl_msg_packet_in *)malloc(sizeof(struct ofl_msg_packet_in));

    dp->buffer_id = ntohl(sp->buffer_id);
    dp->in_port = ntohl(sp->in_port);
    dp->in_phy_port = ntohl(sp->in_phy_port);
    dp->total_len = ntohs(sp->total_len);
    dp->reason = (enum ofp_packet_in_reason)sp->reason;
    dp->table_id = sp->table_id;

    dp->data_length = *len;
    dp->data = *len > 0 ? (uint8_t *)memcpy(malloc(*len), sp->data, *len) : NULL;
    *len = 0;

    *msg = (struct ofl_msg_header *)dp;
    return 0;
}
static ofl_err
ofl_msg_unpack_port_status(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg) {
    struct ofp_port_status *ss;
    struct ofl_msg_port_status *ds;
    ofl_err error;

    if (*len < sizeof(struct ofp_port_status)) {
        OFL_LOG_WARN(LOG_MODULE, "Received PORT_STATUS message has invalid length (%zu).", *len);
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }
    *len -= (sizeof(struct ofp_port_status) - sizeof(struct ofp_port));

    ss = (struct ofp_port_status *)src;
    ds = (struct ofl_msg_port_status *)malloc(sizeof(struct ofl_msg_port_status));

    ds->reason = (enum ofp_port_reason)(ss->reason);

    error = ofl_structs_port_unpack(&(ss->desc), len, &(ds->desc));
    if (error) {
        free(ds);
        return error;
    }

    *msg = (struct ofl_msg_header *)ds;
    return 0;
}
Beispiel #20
0
static ofl_err
ofl_msg_unpack_port_status(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, char *errbuf) {
    struct ofp_port_status *ss;
    struct ofl_msg_port_status *ds;
    ofl_err error;

    if (*len < sizeof(struct ofp_port_status)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received PORT_STATUS message has invalid length (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }
    *len -= (sizeof(struct ofp_port_status) - sizeof(struct ofp_port));

    ss = (struct ofp_port_status *)src;
    ds = (struct ofl_msg_port_status *)malloc(sizeof(struct ofl_msg_port_status));

    ds->reason = ss->reason;

    error = ofl_structs_port_unpack(&(ss->desc), len, &(ds->desc), errbuf);
    if (error) {
        free(ds);
        return error;
    }

    *msg = (struct ofl_msg_header *)ds;
    return 0;
}
Beispiel #21
0
ofl_err
ofl_structs_packet_queue_unpack(struct ofp_packet_queue *src, size_t *len, struct ofl_packet_queue **dst, char *errbuf) {
    struct ofl_packet_queue *q;
    struct ofp_queue_prop_header *prop;
    ofl_err error;
    size_t i;

    if (*len < ntohs(src->len)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received packet queue has invalid length (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }
    *len -= sizeof(struct ofp_packet_queue);

    q = (struct ofl_packet_queue *)malloc(sizeof(struct ofl_packet_queue));
    q->queue_id = ntohl(src->queue_id);

    error = ofl_utils_count_ofp_queue_props((uint8_t *)src->properties, *len, &q->properties_num, errbuf);
    if (error) {
        free(q);
        return error;
    }
    q->properties = (struct ofl_queue_prop_header **)malloc(q->properties_num * sizeof(struct ofl_queue_prop_header *));

    prop = src->properties;
    for (i = 0; i < q->properties_num; i++) {
        ofl_structs_queue_prop_unpack(prop, len, &(q->properties[i]), errbuf);
        //TODO error
        prop = (struct ofp_queue_prop_header *)((uint8_t *)prop + ntohs(prop->len));
    }

    *dst = q;
    return 0;
}
Beispiel #22
0
static ofl_err
ofl_msg_unpack_stats_request_flow(struct ofp_stats_request *os, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp, char *errbuf) {
    struct ofp_flow_stats_request *sm;
    struct ofl_msg_stats_request_flow *dm;
    ofl_err error = 0;

    // ofp_stats_request length was checked at ofl_msg_unpack_stats_request

    if (*len < (sizeof(struct ofp_flow_stats_request) - sizeof(struct ofp_match))) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received FLOW stats request has invalid length (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }
    *len -= (sizeof(struct ofp_flow_stats_request) - sizeof(struct ofp_match));

    sm = (struct ofp_flow_stats_request *)os->body;
    dm = (struct ofl_msg_stats_request_flow *)malloc(sizeof(struct ofl_msg_stats_request_flow));

    dm->table_id = sm->table_id;
    dm->out_port = ntohl(sm->out_port);
    dm->out_group = ntohl(sm->out_group);
    dm->cookie = ntoh64(sm->cookie);
    dm->cookie_mask = ntoh64(sm->cookie_mask);

    error = ofl_structs_match_unpack(&(sm->match), len, &(dm->match), exp, errbuf);
    if (error) {
        free(dm);
        return error;
    }

    *msg = (struct ofl_msg_header *)dm;
    return 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) {
    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;
}
Beispiel #24
0
ofl_err
ATN_ofl_exp_action_unpack (struct ofp_action_header *src, size_t *len, struct ofl_action_header **dst) {
    struct ATN_ofp_action_exp *sa = (struct ATN_ofp_action_exp *)src;
    struct ATN_ofl_action_exp *da = malloc(sizeof(struct ATN_ofl_action_exp));

    if (*len < sizeof(struct ATN_ofp_action_exp)) {
        OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER message has invalid length (%zu).", *len);
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    switch (ntohl(sa->exp_type)) {
        case ATN_OFPAT_PUSH_L2_GRE_HEADER: {
            da->experimenter        = ntohl(sa->header.experimenter);
            da->exp_type            = ntohl(sa->exp_type);
            break;
        }
        case ATN_OFPAT_POP_L2_GRE_HEADER:{
			da->experimenter            = ntohl(sa->header.experimenter);
            da->exp_type                = ntohl(sa->exp_type);
			break;
        }
    }

    *len -= sizeof(struct ATN_ofp_action_exp);
    *dst = (struct ofl_action_header*) da;
    return 0;
}
ofl_err
ofl_structs_packet_queue_unpack(struct ofp_packet_queue *src, size_t *len, struct ofl_packet_queue **dst) {
    struct ofl_packet_queue *q;
    struct ofp_queue_prop_header *prop;
    ofl_err error;
    size_t i;

    if (*len < ntohs(src->len)) {
        OFL_LOG_WARN(LOG_MODULE, "Received packet queue has invalid length (%zu).", *len);
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }
    *len -= sizeof(struct ofp_packet_queue);

    q = (struct ofl_packet_queue *)malloc(sizeof(struct ofl_packet_queue));
    q->queue_id = ntohl(src->queue_id);

    error = ofl_utils_count_ofp_queue_props((uint8_t *)src->properties, ntohs(src->len)-sizeof(struct ofp_packet_queue)/**len*/, &q->properties_num);
    if (error) {
        free(q);
        return error;
    }
    q->properties = (struct ofl_queue_prop_header **)malloc(q->properties_num * sizeof(struct ofl_queue_prop_header *));

    prop = src->properties;
    for (i = 0; i < q->properties_num; i++) {
        ofl_structs_queue_prop_unpack(prop, len, &(q->properties[i]));
        prop = (struct ofp_queue_prop_header *)((uint8_t *)prop + ntohs(prop->len));
    }

    *dst = q;
    return 0;
}
Beispiel #26
0
ofl_err
ofl_structs_queue_prop_unpack(struct ofp_queue_prop_header *src, size_t *len, struct ofl_queue_prop_header **dst, char *errbuf) {

    if (*len < sizeof(struct ofp_action_header)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received queue property 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 queue property has invalid length (set to %u, but only %zu received).", ntohs(src->len), *len);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
    }

    switch (ntohs(src->property)) {
        case OFPQT_MIN_RATE: {
            struct ofp_queue_prop_min_rate *sp = (struct ofp_queue_prop_min_rate *)src;
            struct ofl_queue_prop_min_rate *dp = (struct ofl_queue_prop_min_rate *)malloc(sizeof(struct ofl_queue_prop_min_rate));

            if (*len < sizeof(struct ofp_queue_prop_min_rate)) {
                if (errbuf != NULL) {
                    snprintf(errbuf, OFL_ERRBUF_SIZE, "Received MIN_RATE queue property has invalid length (%zu).", *len);
                }
                return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
            }
            *len -= sizeof(struct ofp_queue_prop_min_rate);

            dp->rate = ntohs(sp->rate);

            *dst = (struct ofl_queue_prop_header *)dp;
            break;
        }
        default: {
            if (errbuf != NULL) {
                snprintf(errbuf, OFL_ERRBUF_SIZE, "Received unknown queue prop type.");
            }
            return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
        }
    }

    (*dst)->type = (enum ofp_queue_properties)ntohs(src->property);
    return 0;
}
Beispiel #27
0
/* Handles flow mod messages with ADD command. */
static ofl_err
flow_table_add(struct flow_table *table, struct ofl_msg_flow_mod *mod, bool check_overlap, bool *match_kept, bool *insts_kept) {
    // Note: new entries will be placed behind those with equal priority
    struct flow_entry *entry, *new_entry;

    LIST_FOR_EACH (entry, struct flow_entry, match_node, &table->match_entries) {
        if (check_overlap && flow_entry_overlaps(entry, mod)) {
            return ofl_error(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP);
        }

        /* if the entry equals, replace the old one */
        if (flow_entry_matches(entry, mod, true/*strict*/, false/*check_cookie*/)) {
            new_entry = flow_entry_create(table->dp, table, mod);
            *match_kept = true;
            *insts_kept = true;

            /* NOTE: no flow removed message should be generated according to spec. */
            list_replace(&new_entry->match_node, &entry->match_node);
            list_remove(&entry->hard_node);
            list_remove(&entry->idle_node);
            flow_entry_destroy(entry);
            add_to_timeout_lists(table, new_entry);
            return 0;
        }

        if (mod->priority > entry->stats->priority) {
            break;
        }
    }

    if (table->stats->active_count == FLOW_TABLE_MAX_ENTRIES) {
        return ofl_error(OFPET_FLOW_MOD_FAILED, OFPFMFC_TABLE_FULL);
    }
    table->stats->active_count++;

    new_entry = flow_entry_create(table->dp, table, mod);
    *match_kept = true;
    *insts_kept = true;

    list_insert(&entry->match_node, &new_entry->match_node);
    add_to_timeout_lists(table, new_entry);

    return 0;
}
ofl_err
ofl_exp_stats_reply_unpack (struct ofp_multipart_reply *os, uint8_t *buf, size_t *len, struct ofl_msg_multipart_reply_header **msg, struct ofl_exp *exp){
    struct ofp_experimenter_stats_header *ext = (struct ofp_experimenter_stats_header *)os->body;

    if (*len < sizeof(struct ofp_experimenter_stats_header)) {
        OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER message is shorter than ofp_experimenter_stats_header.");
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    switch (ntohl(ext->experimenter)) {
        case (OPENSTATE_VENDOR_ID): {
            return ofl_exp_openstate_stats_reply_unpack(os, buf, len, (struct ofl_msg_multipart_reply_header **)msg, exp);
        }
        default: {
            OFL_LOG_WARN(LOG_MODULE, "Trying to unpack unknown EXPERIMENTER message (%u).", ntohl(ext->experimenter));
            return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_EXPERIMENTER);
        }
    }
}
Beispiel #29
0
ofl_err
ofl_exp_stats_req_unpack (struct ofp_multipart_request const *os, uint8_t const *buf, size_t *len,
              struct ofl_msg_multipart_request_header **msg, struct ofl_exp const *exp)
{
    struct ofp_experimenter_stats_header *ext  = (struct ofp_experimenter_stats_header *)os->body;

    if (*len < sizeof(struct ofp_experimenter_stats_header)) {
        OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER message is shorter than ofp_experimenter_stats_header.");
        return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    switch (ntohl(ext->experimenter)) {
        case (BEBA_VENDOR_ID): {
            return ofl_exp_beba_stats_req_unpack(os, buf, len, msg, exp);
        }
        default: {
            OFL_LOG_WARN(LOG_MODULE, "Trying to unpack unknown EXPERIMENTER message %"PRIx32".", ntohl(ext->experimenter));
            return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_EXPERIMENTER);
        }
    }
}
Beispiel #30
0
ofl_err
ofl_structs_port_stats_unpack(struct ofp_port_stats *src, size_t *len, struct ofl_port_stats **dst, char *errbuf) {
    struct ofl_port_stats *p;

    if (*len < sizeof(struct ofp_port_stats)) {
        if (errbuf != NULL) {
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received port stats has invalid length (%zu).", *len);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }
    if (ntohl(src->port_no) == 0 ||
        (ntohl(src->port_no) > OFPP_MAX && ntohl(src->port_no) != OFPP_LOCAL)) {
        if (errbuf != NULL) {
            char *ps = ofl_port_to_string(ntohl(src->port_no));
            snprintf(errbuf, OFL_ERRBUF_SIZE, "Received port stats has invalid port_id (%s).", ps);
            free(ps);
        }
        return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN);
    }
    *len -= sizeof(struct ofp_port_stats);

    p = (struct ofl_port_stats *)malloc(sizeof(struct ofl_port_stats));

    p->port_no      = ntohl(src->port_no);
    p->rx_packets   = ntoh64(src->rx_packets);
    p->tx_packets   = ntoh64(src->tx_packets);
    p->rx_bytes     = ntoh64(src->rx_bytes);
    p->tx_bytes     = ntoh64(src->tx_bytes);
    p->rx_dropped   = ntoh64(src->rx_dropped);
    p->tx_dropped   = ntoh64(src->tx_dropped);
    p->rx_errors    = ntoh64(src->rx_errors);
    p->tx_errors    = ntoh64(src->tx_errors);
    p->rx_frame_err = ntoh64(src->rx_frame_err);
    p->rx_over_err  = ntoh64(src->rx_over_err);
    p->rx_crc_err   = ntoh64(src->rx_crc_err);
    p->collisions   = ntoh64(src->collisions);

    *dst = p;
    return 0;
}