Commit message: ofp-group: Don't assert-fail decoding bad OF1.5 group mod type or command.

When decoding a group mod, the current code validates the group type and
command after the whole group mod has been decoded.  The OF1.5 decoder,
however, tries to use the type and command earlier, when it might still be
invalid.  This caused an assertion failure (via OVS_NOT_REACHED).  This
commit fixes the problem.

ovs-vswitchd does not enable support for OpenFlow 1.5 by default.

Reported-at: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9249
Signed-off-by: Ben Pfaff <blp@ovn.org>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
CVE: CVE-2018-17204
CWE: CWE-617
Vulnerability description: An issue was discovered in Open vSwitch (OvS) 2.7.x through 2.7.6, affecting parse_group_prop_ntr_selection_method in lib/ofp-util.c. When decoding a group mod, it validates the group type and command after the whole group mod has been decoded. The OF1.5 decoder, however, tries to use the type and command earlier, when it might still be invalid. This causes an assertion failure (via OVS_NOT_REACHED). ovs-vswitchd does not enable support for OpenFlow 1.5 by default.

Project: ovs
File: ofp-util.c

bad_group_cmd(enum ofp15_group_mod_command cmd)
{
    const char *opt_version;
    const char *version;
    const char *cmd_str;

    switch (cmd) {
    case OFPGC15_ADD:
    case OFPGC15_MODIFY:
    case OFPGC15_ADD_OR_MOD:
    case OFPGC15_DELETE:
        version = "1.1";
        opt_version = "11";
        break;

    case OFPGC15_INSERT_BUCKET:
    case OFPGC15_REMOVE_BUCKET:
        version = "1.5";
        opt_version = "15";
        break;

    default:
        OVS_NOT_REACHED();
    }

    switch (cmd) {
    case OFPGC15_ADD:
        cmd_str = "add-group";
        break;

    case OFPGC15_MODIFY:
    case OFPGC15_ADD_OR_MOD:
        cmd_str = "mod-group";
        break;

    case OFPGC15_DELETE:
        cmd_str = "del-group";
        break;

    case OFPGC15_INSERT_BUCKET:
        cmd_str = "insert-bucket";
        break;

    case OFPGC15_REMOVE_BUCKET:
        cmd_str = "remove-bucket";
        break;

    default:
        OVS_NOT_REACHED();
    }

    ovs_fatal(0, "%s needs OpenFlow %s or later (\'-O OpenFlow%s\')",
              cmd_str, version, opt_version);

}

Project: ovs
File: ofp-util.c

decode_async_mask(ovs_be32 src,
                  const struct ofp14_async_prop *ap, enum ofp_version version,
                  bool loose, struct ofputil_async_cfg *dst)
{
    uint32_t mask = ntohl(src);
    uint32_t allowed = ofp14_async_prop_allowed(ap, version);
    if (mask & ~allowed) {
        OFPPROP_LOG(&bad_ofmsg_rl, loose,
                    "bad value %#x for %s (allowed mask %#x)",
                    mask, ofputil_async_msg_type_to_string(ap->oam),
                    allowed);
        mask &= allowed;
        if (!loose) {
            return OFPERR_OFPACFC_INVALID;
        }
    }

    if (ap->oam == OAM_PACKET_IN) {
        if (mask & (1u << OFPR_NO_MATCH)) {
            mask |= 1u << OFPR_EXPLICIT_MISS;
            if (version < OFP13_VERSION) {
                mask |= 1u << OFPR_IMPLICIT_MISS;
            }
        }
    }

    uint32_t *array = ap->master ? dst->master : dst->slave;
    array[ap->oam] = mask;
    return 0;
}

Project: ovs
File: ofp-util.c

decode_nx_packet_in2(const struct ofp_header *oh, bool loose,
                     const struct tun_table *tun_table,
                     const struct vl_mff_map *vl_mff_map,
                     struct ofputil_packet_in *pin,
                     size_t *total_len, uint32_t *buffer_id,
                     struct ofpbuf *continuation)
{
    *total_len = 0;
    *buffer_id = UINT32_MAX;

    struct ofpbuf properties;
    ofpbuf_use_const(&properties, oh, ntohs(oh->length));
    ofpraw_pull_assert(&properties);

    while (properties.size > 0) {
        struct ofpbuf payload;
        uint64_t type;

        enum ofperr error = ofpprop_pull(&properties, &payload, &type);
        if (error) {
            return error;
        }

        switch (type) {
        case NXPINT_PACKET:
            pin->packet = payload.msg;
            pin->packet_len = ofpbuf_msgsize(&payload);
            break;

        case NXPINT_FULL_LEN: {
            uint32_t u32;
            error = ofpprop_parse_u32(&payload, &u32);
            *total_len = u32;
            break;
        }

        case NXPINT_BUFFER_ID:
            error = ofpprop_parse_u32(&payload, buffer_id);
            break;

        case NXPINT_TABLE_ID:
            error = ofpprop_parse_u8(&payload, &pin->table_id);
            break;

        case NXPINT_COOKIE:
            error = ofpprop_parse_be64(&payload, &pin->cookie);
            break;

        case NXPINT_REASON: {
            uint8_t reason;
            error = ofpprop_parse_u8(&payload, &reason);
            pin->reason = reason;
            break;
        }

        case NXPINT_METADATA:
            error = oxm_decode_match(payload.msg, ofpbuf_msgsize(&payload),
                                     loose, tun_table, vl_mff_map,
                                     &pin->flow_metadata);
            break;

        case NXPINT_USERDATA:
            pin->userdata = payload.msg;
            pin->userdata_len = ofpbuf_msgsize(&payload);
            break;

        case NXPINT_CONTINUATION:
            if (continuation) {
                error = ofpprop_parse_nested(&payload, continuation);
            }
            break;

        default:
            error = OFPPROP_UNKNOWN(loose, "NX_PACKET_IN2", type);
            break;
        }
        if (error) {
            return error;
        }
    }

    if (!pin->packet_len) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "NXT_PACKET_IN2 lacks packet");
        return OFPERR_OFPBRC_BAD_LEN;
    } else if (!*total_len) {
        *total_len = pin->packet_len;
    } else if (*total_len < pin->packet_len) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "NXT_PACKET_IN2 claimed full_len < len");
        return OFPERR_OFPBRC_BAD_LEN;
    }

    return 0;
}

Project: ovs
File: ofp-util.c

encode_packet_in_reason(enum ofp_packet_in_reason reason,
                        enum ofp_version version)
{
    switch (reason) {
    case OFPR_NO_MATCH:
    case OFPR_ACTION:
    case OFPR_INVALID_TTL:
        return reason;

    case OFPR_ACTION_SET:
    case OFPR_GROUP:
    case OFPR_PACKET_OUT:
        return version < OFP14_VERSION ? OFPR_ACTION : reason;

    case OFPR_EXPLICIT_MISS:
        return version < OFP13_VERSION ? OFPR_ACTION : OFPR_NO_MATCH;

    case OFPR_IMPLICIT_MISS:
        return OFPR_NO_MATCH;

    case OFPR_N_REASONS:
    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

encode_tlv_table_mappings(struct ofpbuf *b, struct ovs_list *mappings)
{
    struct ofputil_tlv_map *map;

    LIST_FOR_EACH (map, list_node, mappings) {
        struct nx_tlv_map *nx_map;

        nx_map = ofpbuf_put_zeros(b, sizeof *nx_map);
        nx_map->option_class = htons(map->option_class);
        nx_map->option_type = map->option_type;
        nx_map->option_len = map->option_len;
        nx_map->index = htons(map->index);
    }
}

Project: ovs
File: ofp-util.c

get_ofp14_async_config_prop_by_oam(enum ofputil_async_msg_type oam,
                                   bool master)
{
    FOR_EACH_ASYNC_PROP (ap) {
        if (ap->oam == oam && ap->master == master) {
            return ap;
        }
    }
    return NULL;
}

Project: ovs
File: ofp-util.c

get_ofp14_async_config_prop_by_prop_type(uint64_t prop_type)
{
    FOR_EACH_ASYNC_PROP (ap) {
        if (prop_type == ap->prop_type) {
            return ap;
        }
    }
    return NULL;
}

Project: ovs
File: ofp-util.c

is_delimiter(unsigned char c)
{
    return isspace(c) || c == ',';
}

Project: ovs
File: ofp-util.c

make_echo_reply(const struct ofp_header *rq)
{
    struct ofpbuf rq_buf = ofpbuf_const_initializer(rq, ntohs(rq->length));
    ofpraw_pull_assert(&rq_buf);

    struct ofpbuf *reply = ofpraw_alloc_reply(OFPRAW_OFPT_ECHO_REPLY,
                                              rq, rq_buf.size);
    ofpbuf_put(reply, rq_buf.data, rq_buf.size);
    return reply;
}

Project: ovs
File: ofp-util.c

make_echo_request(enum ofp_version ofp_version)
{
    return ofpraw_alloc_xid(OFPRAW_OFPT_ECHO_REQUEST, ofp_version,
                            htonl(0), 0);
}

Project: ovs
File: ofp-util.c

mf_bitmap_from_of10(ovs_be32 wc10_)
{
    struct mf_bitmap fields = MF_BITMAP_INITIALIZER;
    const struct ofp10_wc_map *p;
    uint32_t wc10 = ntohl(wc10_);

    for (p = ofp10_wc_map; p < &ofp10_wc_map[ARRAY_SIZE(ofp10_wc_map)]; p++) {
        if (wc10 & p->wc10) {
            bitmap_set1(fields.bm, p->mf);
        }
    }
    return fields;
}

Project: ovs
File: ofp-util.c

mf_bitmap_from_of11(ovs_be32 wc11_)
{
    struct mf_bitmap fields = MF_BITMAP_INITIALIZER;
    const struct ofp11_wc_map *p;
    uint32_t wc11 = ntohl(wc11_);

    for (p = ofp11_wc_map; p < &ofp11_wc_map[ARRAY_SIZE(ofp11_wc_map)]; p++) {
        if (wc11 & p->wc11) {
            bitmap_set1(fields.bm, p->mf);
        }
    }
    return fields;
}

Project: ovs
File: ofp-util.c

mf_bitmap_to_of10(const struct mf_bitmap *fields)
{
    const struct ofp10_wc_map *p;
    uint32_t wc10 = 0;

    for (p = ofp10_wc_map; p < &ofp10_wc_map[ARRAY_SIZE(ofp10_wc_map)]; p++) {
        if (bitmap_is_set(fields->bm, p->mf)) {
            wc10 |= p->wc10;
        }
    }
    return htonl(wc10);
}

Project: ovs
File: ofp-util.c

mf_bitmap_to_of11(const struct mf_bitmap *fields)
{
    const struct ofp11_wc_map *p;
    uint32_t wc11 = 0;

    for (p = ofp11_wc_map; p < &ofp11_wc_map[ARRAY_SIZE(ofp11_wc_map)]; p++) {
        if (bitmap_is_set(fields->bm, p->mf)) {
            wc11 |= p->wc11;
        }
    }
    return htonl(wc11);
}

Project: ovs
File: ofp-util.c

netdev_port_features_from_ofp10(ovs_be32 ofp10_)
{
    uint32_t ofp10 = ntohl(ofp10_);
    return (ofp10 & 0x7f) | ((ofp10 & 0xf80) << 4);
}

Project: ovs
File: ofp-util.c

netdev_port_features_from_ofp11(ovs_be32 ofp11)
{
    return ntohl(ofp11) & 0xffff;
}

Project: ovs
File: ofp-util.c

netdev_port_features_to_ofp10(enum netdev_features features)
{
    return htonl((features & 0x7f) | ((features & 0xf800) >> 4));
}

Project: ovs
File: ofp-util.c

netdev_port_features_to_ofp11(enum netdev_features features)
{
    return htonl(features & 0xffff);
}

Project: ovs
File: ofp-util.c

ofputil_append_flow_update(const struct ofputil_flow_update *update,
                           struct ovs_list *replies,
                           const struct tun_table *tun_table)
{
    struct ofputil_flow_update *update_ =
        CONST_CAST(struct ofputil_flow_update *, update);
    const struct tun_table *orig_tun_table;
    enum ofp_version version = ofpmp_version(replies);
    struct nx_flow_update_header *nfuh;
    struct ofpbuf *msg;
    size_t start_ofs;

    orig_tun_table = update->match.flow.tunnel.metadata.tab;
    update_->match.flow.tunnel.metadata.tab = tun_table;

    msg = ofpbuf_from_list(ovs_list_back(replies));
    start_ofs = msg->size;

    if (update->event == NXFME_ABBREV) {
        struct nx_flow_update_abbrev *nfua;

        nfua = ofpbuf_put_zeros(msg, sizeof *nfua);
        nfua->xid = update->xid;
    } else {
        struct nx_flow_update_full *nfuf;
        int match_len;

        ofpbuf_put_zeros(msg, sizeof *nfuf);
        match_len = nx_put_match(msg, &update->match, htonll(0), htonll(0));
        ofpacts_put_openflow_actions(update->ofpacts, update->ofpacts_len, msg,
                                     version);
        nfuf = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuf);
        nfuf->reason = htons(update->reason);
        nfuf->priority = htons(update->priority);
        nfuf->idle_timeout = htons(update->idle_timeout);
        nfuf->hard_timeout = htons(update->hard_timeout);
        nfuf->match_len = htons(match_len);
        nfuf->table_id = update->table_id;
        nfuf->cookie = update->cookie;
    }

    nfuh = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuh);
    nfuh->length = htons(msg->size - start_ofs);
    nfuh->event = htons(update->event);

    ofpmp_postappend(replies, start_ofs);
    update_->match.flow.tunnel.metadata.tab = orig_tun_table;
}

Project: ovs
File: ofp-util.c

ofputil_append_group_desc_reply(const struct ofputil_group_desc *gds,
                                const struct ovs_list *buckets,
                                struct ovs_list *replies)
{
    enum ofp_version version = ofpmp_version(replies);

    switch (version)
    {
    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION:
    case OFP14_VERSION:
        ofputil_append_ofp11_group_desc_reply(gds, buckets, replies, version);
        break;

    case OFP15_VERSION:
    case OFP16_VERSION:
        ofputil_append_ofp15_group_desc_reply(gds, buckets, replies, version);
        break;

    case OFP10_VERSION:
    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_append_group_stats(struct ovs_list *replies,
                           const struct ofputil_group_stats *gs)
{
    size_t bucket_counter_size;
    struct ofp11_bucket_counter *bucket_counters;
    size_t length;

    bucket_counter_size = gs->n_buckets * sizeof(struct ofp11_bucket_counter);

    switch (ofpmp_version(replies)) {
    case OFP11_VERSION:
    case OFP12_VERSION:{
            struct ofp11_group_stats *gs11;

            length = sizeof *gs11 + bucket_counter_size;
            gs11 = ofpmp_append(replies, length);
            bucket_counters = (struct ofp11_bucket_counter *)(gs11 + 1);
            ofputil_group_stats_to_ofp11(gs, gs11, length, bucket_counters);
            break;
        }

    case OFP13_VERSION:
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION: {
            struct ofp13_group_stats *gs13;

            length = sizeof *gs13 + bucket_counter_size;
            gs13 = ofpmp_append(replies, length);
            bucket_counters = (struct ofp11_bucket_counter *)(gs13 + 1);
            ofputil_group_stats_to_ofp13(gs, gs13, length, bucket_counters);
            break;
        }

    case OFP10_VERSION:
    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_append_ipfix_stat(struct ovs_list *replies,
                         const struct ofputil_ipfix_stats *ois)
{
    struct nx_ipfix_stats_reply *reply = ofpmp_append(replies, sizeof *reply);
    ofputil_ipfix_stats_to_reply(ois, reply);
}

Project: ovs
File: ofp-util.c

ofputil_append_meter_config(struct ovs_list *replies,
                            const struct ofputil_meter_config *mc)
{
    struct ofpbuf *msg = ofpbuf_from_list(ovs_list_back(replies));
    size_t start_ofs = msg->size;
    struct ofp13_meter_config *reply;

    ofpbuf_put_uninit(msg, sizeof *reply);
    ofputil_put_bands(mc->n_bands, mc->bands, msg);

    reply = ofpbuf_at_assert(msg, start_ofs, sizeof *reply);
    reply->flags = htons(mc->flags);
    reply->meter_id = htonl(mc->meter_id);
    reply->length = htons(msg->size - start_ofs);

    ofpmp_postappend(replies, start_ofs);
}

Project: ovs
File: ofp-util.c

ofputil_append_meter_stats(struct ovs_list *replies,
                           const struct ofputil_meter_stats *ms)
{
    struct ofp13_meter_stats *reply;
    uint16_t n = 0;
    uint16_t len;

    len = sizeof *reply + ms->n_bands * sizeof(struct ofp13_meter_band_stats);
    reply = ofpmp_append(replies, len);

    reply->meter_id = htonl(ms->meter_id);
    reply->len = htons(len);
    memset(reply->pad, 0, sizeof reply->pad);
    reply->flow_count = htonl(ms->flow_count);
    reply->packet_in_count = htonll(ms->packet_in_count);
    reply->byte_in_count = htonll(ms->byte_in_count);
    reply->duration_sec = htonl(ms->duration_sec);
    reply->duration_nsec = htonl(ms->duration_nsec);

    for (n = 0; n < ms->n_bands; ++n) {
        const struct ofputil_meter_band_stats *src = &ms->bands[n];
        struct ofp13_meter_band_stats *dst = &reply->band_stats[n];

        dst->packet_band_count = htonll(src->packet_count);
        dst->byte_band_count = htonll(src->byte_count);
    }
}

Project: ovs
File: ofp-util.c

ofputil_append_ofp11_group_desc_reply(const struct ofputil_group_desc *gds,
                                      const struct ovs_list *buckets,
                                      struct ovs_list *replies,
                                      enum ofp_version version)
{
    struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
    struct ofp11_group_desc_stats *ogds;
    struct ofputil_bucket *bucket;
    size_t start_ogds;

    start_ogds = reply->size;
    ofpbuf_put_zeros(reply, sizeof *ogds);
    LIST_FOR_EACH (bucket, list_node, buckets) {
        ofputil_put_ofp11_bucket(bucket, reply, version);
    }
    ogds = ofpbuf_at_assert(reply, start_ogds, sizeof *ogds);
    ogds->length = htons(reply->size - start_ogds);
    ogds->type = gds->type;
    ogds->group_id = htonl(gds->group_id);

    ofpmp_postappend(replies, start_ogds);
}

Project: ovs
File: ofp-util.c

ofputil_append_ofp14_port_stats(const struct ofputil_port_stats *ops,
                                struct ovs_list *replies)
{
    struct ofp14_port_stats_prop_ethernet *eth;
    struct intel_port_stats_rfc2819 *stats_rfc2819;
    struct ofp14_port_stats *ps14;
    struct ofpbuf *reply;

    reply = ofpmp_reserve(replies, sizeof *ps14 + sizeof *eth +
                          sizeof *stats_rfc2819);

    ps14 = ofpbuf_put_uninit(reply, sizeof *ps14);
    ps14->length = htons(sizeof *ps14 + sizeof *eth +
                         sizeof *stats_rfc2819);
    memset(ps14->pad, 0, sizeof ps14->pad);
    ps14->port_no = ofputil_port_to_ofp11(ops->port_no);
    ps14->duration_sec = htonl(ops->duration_sec);
    ps14->duration_nsec = htonl(ops->duration_nsec);
    ps14->rx_packets = htonll(ops->stats.rx_packets);
    ps14->tx_packets = htonll(ops->stats.tx_packets);
    ps14->rx_bytes = htonll(ops->stats.rx_bytes);
    ps14->tx_bytes = htonll(ops->stats.tx_bytes);
    ps14->rx_dropped = htonll(ops->stats.rx_dropped);
    ps14->tx_dropped = htonll(ops->stats.tx_dropped);
    ps14->rx_errors = htonll(ops->stats.rx_errors);
    ps14->tx_errors = htonll(ops->stats.tx_errors);

    eth = ofpprop_put_zeros(reply, OFPPSPT14_ETHERNET, sizeof *eth);
    eth->rx_frame_err = htonll(ops->stats.rx_frame_errors);
    eth->rx_over_err = htonll(ops->stats.rx_over_errors);
    eth->rx_crc_err = htonll(ops->stats.rx_crc_errors);
    eth->collisions = htonll(ops->stats.collisions);

    uint64_t prop_type = OFPPROP_EXP(INTEL_VENDOR_ID,
                                     INTEL_PORT_STATS_RFC2819);

    stats_rfc2819 = ofpprop_put_zeros(reply, prop_type,
                                      sizeof *stats_rfc2819);

    memset(stats_rfc2819->pad, 0, sizeof stats_rfc2819->pad);
    stats_rfc2819->rx_1_to_64_packets = htonll(ops->stats.rx_1_to_64_packets);
    stats_rfc2819->rx_65_to_127_packets =
        htonll(ops->stats.rx_65_to_127_packets);
    stats_rfc2819->rx_128_to_255_packets =
        htonll(ops->stats.rx_128_to_255_packets);
    stats_rfc2819->rx_256_to_511_packets =
        htonll(ops->stats.rx_256_to_511_packets);
    stats_rfc2819->rx_512_to_1023_packets =
        htonll(ops->stats.rx_512_to_1023_packets);
    stats_rfc2819->rx_1024_to_1522_packets =
        htonll(ops->stats.rx_1024_to_1522_packets);
    stats_rfc2819->rx_1523_to_max_packets =
        htonll(ops->stats.rx_1523_to_max_packets);

    stats_rfc2819->tx_1_to_64_packets = htonll(ops->stats.tx_1_to_64_packets);
    stats_rfc2819->tx_65_to_127_packets =
        htonll(ops->stats.tx_65_to_127_packets);
    stats_rfc2819->tx_128_to_255_packets =
        htonll(ops->stats.tx_128_to_255_packets);
    stats_rfc2819->tx_256_to_511_packets =
        htonll(ops->stats.tx_256_to_511_packets);
    stats_rfc2819->tx_512_to_1023_packets =
        htonll(ops->stats.tx_512_to_1023_packets);
    stats_rfc2819->tx_1024_to_1522_packets =
        htonll(ops->stats.tx_1024_to_1522_packets);
    stats_rfc2819->tx_1523_to_max_packets =
        htonll(ops->stats.tx_1523_to_max_packets);

    stats_rfc2819->tx_multicast_packets =
        htonll(ops->stats.tx_multicast_packets);
    stats_rfc2819->rx_broadcast_packets =
        htonll(ops->stats.rx_broadcast_packets);
    stats_rfc2819->tx_broadcast_packets =
        htonll(ops->stats.tx_broadcast_packets);
    stats_rfc2819->rx_undersized_errors =
        htonll(ops->stats.rx_undersized_errors);
    stats_rfc2819->rx_oversize_errors =
        htonll(ops->stats.rx_oversize_errors);
    stats_rfc2819->rx_fragmented_errors =
        htonll(ops->stats.rx_fragmented_errors);
    stats_rfc2819->rx_jabber_errors =
        htonll(ops->stats.rx_jabber_errors);
}

Project: ovs
File: ofp-util.c

ofputil_append_ofp15_group_desc_reply(const struct ofputil_group_desc *gds,
                                      const struct ovs_list *buckets,
                                      struct ovs_list *replies,
                                      enum ofp_version version)
{
    struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
    struct ofp15_group_desc_stats *ogds;
    struct ofputil_bucket *bucket;
    size_t start_ogds, start_buckets;

    start_ogds = reply->size;
    ofpbuf_put_zeros(reply, sizeof *ogds);
    start_buckets = reply->size;
    LIST_FOR_EACH (bucket, list_node, buckets) {
        ofputil_put_ofp15_bucket(bucket, bucket->bucket_id,
                                 gds->type, reply, version);
    }
    ogds = ofpbuf_at_assert(reply, start_ogds, sizeof *ogds);
    ogds->type = gds->type;
    ogds->group_id = htonl(gds->group_id);
    ogds->bucket_list_len =  htons(reply->size - start_buckets);

    /* Add group properties */
    if (gds->props.selection_method[0]) {
        ofputil_put_group_prop_ntr_selection_method(version, &gds->props,
                                                    reply);
    }
    ogds = ofpbuf_at_assert(reply, start_ogds, sizeof *ogds);
    ogds->length = htons(reply->size - start_ogds);

    ofpmp_postappend(replies, start_ogds);
}

Project: ovs
File: ofp-util.c

ofputil_append_port_desc_stats_reply(const struct ofputil_phy_port *pp,
                                     struct ovs_list *replies)
{
    struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
    size_t start_ofs = reply->size;

    ofputil_put_phy_port(ofpmp_version(replies), pp, reply);
    ofpmp_postappend(replies, start_ofs);
}

Project: ovs
File: ofp-util.c

ofputil_append_port_stat(struct ovs_list *replies,
                         const struct ofputil_port_stats *ops)
{
    switch (ofpmp_version(replies)) {
    case OFP13_VERSION: {
        struct ofp13_port_stats *reply = ofpmp_append(replies, sizeof *reply);
        ofputil_port_stats_to_ofp13(ops, reply);
        break;
    }
    case OFP12_VERSION:
    case OFP11_VERSION: {
        struct ofp11_port_stats *reply = ofpmp_append(replies, sizeof *reply);
        ofputil_port_stats_to_ofp11(ops, reply);
        break;
    }

    case OFP10_VERSION: {
        struct ofp10_port_stats *reply = ofpmp_append(replies, sizeof *reply);
        ofputil_port_stats_to_ofp10(ops, reply);
        break;
    }

    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION:
        ofputil_append_ofp14_port_stats(ops, replies);
        break;

    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_append_queue_get_config_reply(const struct ofputil_queue_config *qc,
                                      struct ovs_list *replies)
{
    enum ofp_version ofp_version = ofpmp_version(replies);
    struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
    size_t start_ofs = reply->size;
    size_t len_ofs;
    ovs_be16 *len;

    if (ofp_version < OFP14_VERSION) {
        if (ofp_version < OFP12_VERSION) {
            struct ofp10_packet_queue *opq10;

            opq10 = ofpbuf_put_zeros(reply, sizeof *opq10);
            opq10->queue_id = htonl(qc->queue);
            len_ofs = (char *) &opq10->len - (char *) reply->data;
        } else {
            struct ofp12_packet_queue *opq12;

            opq12 = ofpbuf_put_zeros(reply, sizeof *opq12);
            opq12->port = ofputil_port_to_ofp11(qc->port);
            opq12->queue_id = htonl(qc->queue);
            len_ofs = (char *) &opq12->len - (char *) reply->data;
        }

        put_ofp10_queue_rate(reply, OFPQT10_MIN_RATE, qc->min_rate);
        put_ofp10_queue_rate(reply, OFPQT11_MAX_RATE, qc->max_rate);
    } else {
        struct ofp14_queue_desc *oqd = ofpbuf_put_zeros(reply, sizeof *oqd);
        oqd->port_no = ofputil_port_to_ofp11(qc->port);
        oqd->queue_id = htonl(qc->queue);
        len_ofs = (char *) &oqd->len - (char *) reply->data;
        put_ofp14_queue_rate(reply, OFPQDPT14_MIN_RATE, qc->min_rate);
        put_ofp14_queue_rate(reply, OFPQDPT14_MAX_RATE, qc->max_rate);
    }

    len = ofpbuf_at(reply, len_ofs, sizeof *len);
    *len = htons(reply->size - start_ofs);

    if (ofp_version >= OFP14_VERSION) {
        ofpmp_postappend(replies, start_ofs);
    }
}

Project: ovs
File: ofp-util.c

ofputil_append_queue_stat(struct ovs_list *replies,
                          const struct ofputil_queue_stats *oqs)
{
    switch (ofpmp_version(replies)) {
    case OFP13_VERSION: {
        struct ofp13_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
        ofputil_queue_stats_to_ofp13(oqs, reply);
        break;
    }

    case OFP12_VERSION:
    case OFP11_VERSION: {
        struct ofp11_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
        ofputil_queue_stats_to_ofp11(oqs, reply);
        break;
    }

    case OFP10_VERSION: {
        struct ofp10_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
        ofputil_queue_stats_to_ofp10(oqs, reply);
        break;
    }

    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION: {
        struct ofp14_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
        ofputil_queue_stats_to_ofp14(oqs, reply);
        break;
    }

    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_append_table_desc_reply(const struct ofputil_table_desc *td,
                                struct ovs_list *replies,
                                enum ofp_version version)
{
    struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
    size_t start_otd;
    struct ofp14_table_desc *otd;

    start_otd = reply->size;
    ofpbuf_put_zeros(reply, sizeof *otd);
    if (td->eviction_flags != UINT32_MAX) {
        ofpprop_put_u32(reply, OFPTMPT14_EVICTION, td->eviction_flags);
    }
    if (td->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
        struct ofp14_table_mod_prop_vacancy *otv;

        otv = ofpprop_put_zeros(reply, OFPTMPT14_VACANCY, sizeof *otv);
        otv->vacancy_down = td->table_vacancy.vacancy_down;
        otv->vacancy_up = td->table_vacancy.vacancy_up;
        otv->vacancy = td->table_vacancy.vacancy;
    }

    otd = ofpbuf_at_assert(reply, start_otd, sizeof *otd);
    otd->length = htons(reply->size - start_otd);
    otd->table_id = td->table_id;
    otd->config = ofputil_encode_table_config(OFPUTIL_TABLE_MISS_DEFAULT,
                                              td->eviction, td->vacancy,
                                              version);
    ofpmp_postappend(replies, start_otd);
}

Project: ovs
File: ofp-util.c

ofputil_append_table_features_reply(const struct ofputil_table_features *tf,
                                    struct ovs_list *replies)
{
    struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
    enum ofp_version version = ofpmp_version(replies);
    size_t start_ofs = reply->size;
    struct ofp13_table_features *otf;

    otf = ofpbuf_put_zeros(reply, sizeof *otf);
    otf->table_id = tf->table_id;
    ovs_strlcpy(otf->name, tf->name, sizeof otf->name);
    otf->metadata_match = tf->metadata_match;
    otf->metadata_write = tf->metadata_write;
    if (version >= OFP14_VERSION) {
        if (tf->supports_eviction) {
            otf->capabilities |= htonl(OFPTC14_EVICTION);
        }
        if (tf->supports_vacancy_events) {
            otf->capabilities |= htonl(OFPTC14_VACANCY_EVENTS);
        }
    }
    otf->max_entries = htonl(tf->max_entries);

    put_table_instruction_features(reply, &tf->nonmiss, 0, version);
    put_table_instruction_features(reply, &tf->miss, 1, version);

    put_fields_property(reply, &tf->match, &tf->mask,
                        OFPTFPT13_MATCH, version);
    put_fields_property(reply, &tf->wildcard, NULL,
                        OFPTFPT13_WILDCARDS, version);

    otf = ofpbuf_at_assert(reply, start_ofs, sizeof *otf);
    otf->length = htons(reply->size - start_ofs);
    ofpmp_postappend(replies, start_ofs);
}

Project: ovs
File: ofp-util.c

ofputil_append_table_stats_reply(struct ofpbuf *reply,
                                 const struct ofputil_table_stats *stats,
                                 const struct ofputil_table_features *features)
{
    struct ofp_header *oh = reply->header;

    ovs_assert(stats->table_id == features->table_id);

    switch ((enum ofp_version) oh->version) {
    case OFP10_VERSION:
        ofputil_put_ofp10_table_stats(stats, features, reply);
        break;

    case OFP11_VERSION:
        ofputil_put_ofp11_table_stats(stats, features, reply);
        break;

    case OFP12_VERSION:
        ofputil_put_ofp12_table_stats(stats, features, reply);
        break;

    case OFP13_VERSION:
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION:
        ofputil_put_ofp13_table_stats(stats, reply);
        break;

    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_async_cfg_default(enum ofp_version version)
{
    /* We enable all of the OF1.4 reasons regardless of 'version' because the
     * reasons added in OF1.4 just are just refinements of the OFPR_ACTION
     * introduced in OF1.0, breaking it into more specific categories.  When we
     * encode these for earlier OpenFlow versions, we translate them into
     * OFPR_ACTION.  */
    uint32_t pin = OFPR14_BITS & ~(1u << OFPR_INVALID_TTL);
    pin |= 1u << OFPR_EXPLICIT_MISS;
    if (version <= OFP12_VERSION) {
        pin |= 1u << OFPR_IMPLICIT_MISS;
    }

    return (struct ofputil_async_cfg) {
        .master[OAM_PACKET_IN] = pin,

        .master[OAM_FLOW_REMOVED]
            = (version >= OFP14_VERSION ? OFPRR14_BITS : OFPRR10_BITS),

        .master[OAM_PORT_STATUS] = OFPPR_BITS,
        .slave[OAM_PORT_STATUS] = OFPPR_BITS,
    };
}

Project: ovs
File: ofp-util.c

ofputil_async_msg_type_to_string(enum ofputil_async_msg_type type)
{
    switch (type) {
    case OAM_PACKET_IN:      return "PACKET_IN";
    case OAM_PORT_STATUS:    return "PORT_STATUS";
    case OAM_FLOW_REMOVED:   return "FLOW_REMOVED";
    case OAM_ROLE_STATUS:    return "ROLE_STATUS";
    case OAM_TABLE_STATUS:   return "TABLE_STATUS";
    case OAM_REQUESTFORWARD: return "REQUESTFORWARD";

    case OAM_N_TYPES:
    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_bucket_check_duplicate_id(const struct ovs_list *buckets)
{
    struct ofputil_bucket *i, *j;

    LIST_FOR_EACH (i, list_node, buckets) {
        LIST_FOR_EACH_REVERSE (j, list_node, buckets) {
            if (i == j) {
                break;
            }
            if (i->bucket_id == j->bucket_id) {
                return true;
            }
        }
    }

    return false;
}

Project: ovs
File: ofp-util.c

ofputil_bucket_clone_list(struct ovs_list *dest, const struct ovs_list *src,
                          const struct ofputil_bucket *skip)
{
    struct ofputil_bucket *bucket;

    LIST_FOR_EACH (bucket, list_node, src) {
        struct ofputil_bucket *new_bucket;

        if (bucket == skip) {
            continue;
        }

        new_bucket = ofputil_bucket_clone_data(bucket);
        ovs_list_push_back(dest, &new_bucket->list_node);
    }
}

Project: ovs
File: ofp-util.c

ofputil_bucket_find(const struct ovs_list *buckets, uint32_t bucket_id)
{
    struct ofputil_bucket *bucket;

    if (bucket_id > OFPG15_BUCKET_MAX) {
        return NULL;
    }

    LIST_FOR_EACH (bucket, list_node, buckets) {
        if (bucket->bucket_id == bucket_id) {
            return bucket;
        }
    }

    return NULL;
}

Project: ovs
File: ofp-util.c

ofputil_bucket_list_back(const struct ovs_list *buckets)
{
    static struct ofputil_bucket *bucket;

    ASSIGN_CONTAINER(bucket, ovs_list_back(buckets), list_node);

    return bucket;
}

Project: ovs
File: ofp-util.c

ofputil_bucket_list_destroy(struct ovs_list *buckets)
{
    struct ofputil_bucket *bucket;

    LIST_FOR_EACH_POP (bucket, list_node, buckets) {
        free(bucket->ofpacts);
        free(bucket);
    }
}

Project: ovs
File: ofp-util.c

ofputil_check_group_mod(const struct ofputil_group_mod *gm)
{
    switch (gm->type) {
    case OFPGT11_INDIRECT:
        if (gm->command != OFPGC11_DELETE
            && !ovs_list_is_singleton(&gm->buckets) ) {
            return OFPERR_OFPGMFC_INVALID_GROUP;
        }
        break;
    case OFPGT11_ALL:
    case OFPGT11_SELECT:
    case OFPGT11_FF:
        break;
    default:
        return OFPERR_OFPGMFC_BAD_TYPE;
    }

    switch (gm->command) {
    case OFPGC11_ADD:
    case OFPGC11_MODIFY:
    case OFPGC11_ADD_OR_MOD:
    case OFPGC11_DELETE:
    case OFPGC15_INSERT_BUCKET:
        break;
    case OFPGC15_REMOVE_BUCKET:
        if (!ovs_list_is_empty(&gm->buckets)) {
            return OFPERR_OFPGMFC_BAD_BUCKET;
        }
        break;
    default:
        return OFPERR_OFPGMFC_BAD_COMMAND;
    }

    struct ofputil_bucket *bucket;
    LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
        if (bucket->weight && gm->type != OFPGT11_SELECT) {
            return OFPERR_OFPGMFC_INVALID_GROUP;
        }

        switch (gm->type) {
        case OFPGT11_ALL:
        case OFPGT11_INDIRECT:
            if (ofputil_bucket_has_liveness(bucket)) {
                return OFPERR_OFPGMFC_WATCH_UNSUPPORTED;
            }
            break;
        case OFPGT11_SELECT:
            break;
        case OFPGT11_FF:
            if (!ofputil_bucket_has_liveness(bucket)) {
                return OFPERR_OFPGMFC_INVALID_GROUP;
            }
            break;
        default:
            /* Returning BAD TYPE to be consistent
             * though gm->type has been checked already. */
            return OFPERR_OFPGMFC_BAD_TYPE;
        }
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_count_ipfix_stats(const struct ofp_header *oh)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    ofpraw_pull_assert(&b);

    return b.size / sizeof(struct ofputil_ipfix_stats);
}

Project: ovs
File: ofp-util.c

ofputil_count_port_stats(const struct ofp_header *oh)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    ofpraw_pull_assert(&b);

    for (size_t n = 0; ; n++) {
        struct ofputil_port_stats ps;
        if (ofputil_decode_port_stats(&ps, &b)) {
            return n;
        }
    }
}

Project: ovs
File: ofp-util.c

ofputil_count_queue_stats(const struct ofp_header *oh)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    ofpraw_pull_assert(&b);

    for (size_t n = 0; ; n++) {
        struct ofputil_queue_stats qs;
        if (ofputil_decode_queue_stats(&qs, &b)) {
            return n;
        }
    }
}

Project: ovs
File: ofp-util.c

ofputil_decode_aggregate_stats_reply(struct ofputil_aggregate_stats *stats,
                                     const struct ofp_header *reply)
{
    struct ofpbuf msg = ofpbuf_const_initializer(reply, ntohs(reply->length));
    ofpraw_pull_assert(&msg);

    struct ofp_aggregate_stats_reply *asr = msg.msg;
    stats->packet_count = ntohll(get_32aligned_be64(&asr->packet_count));
    stats->byte_count = ntohll(get_32aligned_be64(&asr->byte_count));
    stats->flow_count = ntohl(asr->flow_count);

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_bundle_add(const struct ofp_header *oh,
                          struct ofputil_bundle_add_msg *msg,
                          enum ofptype *typep)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));

    /* Pull the outer ofp_header. */
    enum ofpraw raw = ofpraw_pull_assert(&b);
    ovs_assert(raw == OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE
               || raw == OFPRAW_ONFT13_BUNDLE_ADD_MESSAGE);

    /* Pull the bundle_ctrl header. */
    const struct ofp14_bundle_ctrl_msg *m = ofpbuf_pull(&b, sizeof *m);
    msg->bundle_id = ntohl(m->bundle_id);
    msg->flags = ntohs(m->flags);

    /* Pull the inner ofp_header. */
    if (b.size < sizeof(struct ofp_header)) {
        return OFPERR_OFPBFC_MSG_BAD_LEN;
    }
    msg->msg = b.data;
    if (msg->msg->version != oh->version) {
        return OFPERR_OFPBFC_BAD_VERSION;
    }
    size_t inner_len = ntohs(msg->msg->length);
    if (inner_len < sizeof(struct ofp_header) || inner_len > b.size) {
        return OFPERR_OFPBFC_MSG_BAD_LEN;
    }
    if (msg->msg->xid != oh->xid) {
        return OFPERR_OFPBFC_MSG_BAD_XID;
    }

    /* Reject unbundlable messages. */
    enum ofptype type;
    enum ofperr error = ofptype_decode(&type, msg->msg);
    if (error) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "OFPT14_BUNDLE_ADD_MESSAGE contained "
                     "message is unparsable (%s)", ofperr_get_name(error));
        return OFPERR_OFPBFC_MSG_UNSUP; /* 'error' would be confusing. */
    }

    if (!ofputil_is_bundlable(type)) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "%s message not allowed inside "
                     "OFPT14_BUNDLE_ADD_MESSAGE", ofptype_get_name(type));
        return OFPERR_OFPBFC_MSG_UNSUP;
    }
    if (typep) {
        *typep = type;
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_bundle_ctrl(const struct ofp_header *oh,
                           struct ofputil_bundle_ctrl_msg *msg)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);
    ovs_assert(raw == OFPRAW_OFPT14_BUNDLE_CONTROL
               || raw == OFPRAW_ONFT13_BUNDLE_CONTROL);

    const struct ofp14_bundle_ctrl_msg *m = b.msg;
    msg->bundle_id = ntohl(m->bundle_id);
    msg->type = ntohs(m->type);
    msg->flags = ntohs(m->flags);

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
                        const struct ofp_header *oh,
                        enum ofputil_protocol protocol,
                        const struct tun_table *tun_table,
                        const struct vl_mff_map *vl_mff_map,
                        struct ofpbuf *ofpacts,
                        ofp_port_t max_port, uint8_t max_table)
{
    ovs_be16 raw_flags;
    enum ofperr error;
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);
    if (raw == OFPRAW_OFPT11_FLOW_MOD) {
        /* Standard OpenFlow 1.1+ flow_mod. */
        const struct ofp11_flow_mod *ofm;

        ofm = ofpbuf_pull(&b, sizeof *ofm);

        error = ofputil_pull_ofp11_match(&b, tun_table, vl_mff_map, &fm->match,
                                         NULL);
        if (error) {
            return error;
        }

        /* Translate the message. */
        fm->priority = ntohs(ofm->priority);
        if (ofm->command == OFPFC_ADD
            || (oh->version == OFP11_VERSION
                && (ofm->command == OFPFC_MODIFY ||
                    ofm->command == OFPFC_MODIFY_STRICT)
                && ofm->cookie_mask == htonll(0))) {
            /* In OpenFlow 1.1 only, a "modify" or "modify-strict" that does
             * not match on the cookie is treated as an "add" if there is no
             * match. */
            fm->cookie = htonll(0);
            fm->cookie_mask = htonll(0);
            fm->new_cookie = ofm->cookie;
        } else {
            fm->cookie = ofm->cookie;
            fm->cookie_mask = ofm->cookie_mask;
            fm->new_cookie = OVS_BE64_MAX;
        }
        fm->modify_cookie = false;
        fm->command = ofm->command;

        /* Get table ID.
         *
         * OF1.1 entirely forbids table_id == OFPTT_ALL.
         * OF1.2+ allows table_id == OFPTT_ALL only for deletes. */
        fm->table_id = ofm->table_id;
        if (fm->table_id == OFPTT_ALL
            && (oh->version == OFP11_VERSION
                || (ofm->command != OFPFC_DELETE &&
                    ofm->command != OFPFC_DELETE_STRICT))) {
            return OFPERR_OFPFMFC_BAD_TABLE_ID;
        }

        fm->idle_timeout = ntohs(ofm->idle_timeout);
        fm->hard_timeout = ntohs(ofm->hard_timeout);
        if (oh->version >= OFP14_VERSION && ofm->command == OFPFC_ADD) {
            fm->importance = ntohs(ofm->importance);
        } else {
            fm->importance = 0;
        }
        fm->buffer_id = ntohl(ofm->buffer_id);
        error = ofputil_port_from_ofp11(ofm->out_port, &fm->out_port);
        if (error) {
            return error;
        }

        fm->out_group = (ofm->command == OFPFC_DELETE ||
                         ofm->command == OFPFC_DELETE_STRICT
                         ? ntohl(ofm->out_group)
                         : OFPG_ANY);
        raw_flags = ofm->flags;
    } else {
        uint16_t command;

        if (raw == OFPRAW_OFPT10_FLOW_MOD) {
            /* Standard OpenFlow 1.0 flow_mod. */
            const struct ofp10_flow_mod *ofm;

            /* Get the ofp10_flow_mod. */
            ofm = ofpbuf_pull(&b, sizeof *ofm);

            /* Translate the rule. */
            ofputil_match_from_ofp10_match(&ofm->match, &fm->match);
            ofputil_normalize_match(&fm->match);

            /* OpenFlow 1.0 says that exact-match rules have to have the
             * highest possible priority. */
            fm->priority = (ofm->match.wildcards & htonl(OFPFW10_ALL)
                            ? ntohs(ofm->priority)
                            : UINT16_MAX);

            /* Translate the message. */
            command = ntohs(ofm->command);
            fm->cookie = htonll(0);
            fm->cookie_mask = htonll(0);
            fm->new_cookie = ofm->cookie;
            fm->idle_timeout = ntohs(ofm->idle_timeout);
            fm->hard_timeout = ntohs(ofm->hard_timeout);
            fm->importance = 0;
            fm->buffer_id = ntohl(ofm->buffer_id);
            fm->out_port = u16_to_ofp(ntohs(ofm->out_port));
            fm->out_group = OFPG_ANY;
            raw_flags = ofm->flags;
        } else if (raw == OFPRAW_NXT_FLOW_MOD) {
            /* Nicira extended flow_mod. */
            const struct nx_flow_mod *nfm;

            /* Dissect the message. */
            nfm = ofpbuf_pull(&b, sizeof *nfm);
            error = nx_pull_match(&b, ntohs(nfm->match_len),
                                  &fm->match, &fm->cookie, &fm->cookie_mask,
                                  tun_table, vl_mff_map);
            if (error) {
                return error;
            }

            /* Translate the message. */
            command = ntohs(nfm->command);
            if ((command & 0xff) == OFPFC_ADD && fm->cookie_mask) {
                /* Flow additions may only set a new cookie, not match an
                 * existing cookie. */
                return OFPERR_NXBRC_NXM_INVALID;
            }
            fm->priority = ntohs(nfm->priority);
            fm->new_cookie = nfm->cookie;
            fm->idle_timeout = ntohs(nfm->idle_timeout);
            fm->hard_timeout = ntohs(nfm->hard_timeout);
            fm->importance = 0;
            fm->buffer_id = ntohl(nfm->buffer_id);
            fm->out_port = u16_to_ofp(ntohs(nfm->out_port));
            fm->out_group = OFPG_ANY;
            raw_flags = nfm->flags;
        } else {
            OVS_NOT_REACHED();
        }

        fm->modify_cookie = fm->new_cookie != OVS_BE64_MAX;
        if (protocol & OFPUTIL_P_TID) {
            fm->command = command & 0xff;
            fm->table_id = command >> 8;
        } else {
            if (command > 0xff) {
                VLOG_WARN_RL(&bad_ofmsg_rl, "flow_mod has explicit table_id "
                             "but flow_mod_table_id extension is not enabled");
            }
            fm->command = command;
            fm->table_id = 0xff;
        }
    }

    if (fm->command > OFPFC_DELETE_STRICT) {
        return OFPERR_OFPFMFC_BAD_COMMAND;
    }

    fm->ofpacts_tlv_bitmap = 0;
    error = ofpacts_pull_openflow_instructions(&b, b.size, oh->version,
                                               vl_mff_map,
                                               &fm->ofpacts_tlv_bitmap,
                                               ofpacts);
    if (error) {
        return error;
    }
    fm->ofpacts = ofpacts->data;
    fm->ofpacts_len = ofpacts->size;

    error = ofputil_decode_flow_mod_flags(raw_flags, fm->command,
                                          oh->version, &fm->flags);
    if (error) {
        return error;
    }

    if (fm->flags & OFPUTIL_FF_EMERG) {
        /* We do not support the OpenFlow 1.0 emergency flow cache, which
         * is not required in OpenFlow 1.0.1 and removed from OpenFlow 1.1.
         *
         * OpenFlow 1.0 specifies the error code to use when idle_timeout
         * or hard_timeout is nonzero.  Otherwise, there is no good error
         * code, so just state that the flow table is full. */
        return (fm->hard_timeout || fm->idle_timeout
                ? OFPERR_OFPFMFC_BAD_EMERG_TIMEOUT
                : OFPERR_OFPFMFC_TABLE_FULL);
    }

    return ofpacts_check_consistency(fm->ofpacts, fm->ofpacts_len,
                                     &fm->match.flow, max_port,
                                     fm->table_id, max_table, protocol);
}

Project: ovs
File: ofp-util.c

ofputil_decode_flow_mod_flags(ovs_be16 raw_flags_,
                              enum ofp_flow_mod_command command,
                              enum ofp_version version,
                              enum ofputil_flow_mod_flags *flagsp)
{
    uint16_t raw_flags = ntohs(raw_flags_);
    const struct ofputil_flow_mod_flag *f;

    *flagsp = 0;
    for (f = ofputil_flow_mod_flags; f->raw_flag; f++) {
        if (raw_flags & f->raw_flag
            && version >= f->min_version
            && (!f->max_version || version <= f->max_version)) {
            raw_flags &= ~f->raw_flag;
            *flagsp |= f->flag;
        }
    }

    /* In OF1.0 and OF1.1, "add" always resets counters, and other commands
     * never do.
     *
     * In OF1.2 and later, OFPFF12_RESET_COUNTS controls whether each command
     * resets counters. */
    if ((version == OFP10_VERSION || version == OFP11_VERSION)
        && command == OFPFC_ADD) {
        *flagsp |= OFPUTIL_FF_RESET_COUNTS;
    }

    return raw_flags ? OFPERR_OFPFMFC_BAD_FLAGS : 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_flow_monitor_cancel(const struct ofp_header *oh)
{
    const struct nx_flow_monitor_cancel *cancel = ofpmsg_body(oh);

    return ntohl(cancel->id);
}

Project: ovs
File: ofp-util.c

ofputil_decode_flow_monitor_request(struct ofputil_flow_monitor_request *rq,
                                    struct ofpbuf *msg)
{
    struct nx_flow_monitor_request *nfmr;
    uint16_t flags;

    if (!msg->header) {
        ofpraw_pull_assert(msg);
    }

    if (!msg->size) {
        return EOF;
    }

    nfmr = ofpbuf_try_pull(msg, sizeof *nfmr);
    if (!nfmr) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR request has %"PRIu32" "
                     "leftover bytes at end", msg->size);
        return OFPERR_OFPBRC_BAD_LEN;
    }

    flags = ntohs(nfmr->flags);
    if (!(flags & (NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY))
        || flags & ~(NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE
                     | NXFMF_MODIFY | NXFMF_ACTIONS | NXFMF_OWN)) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR has bad flags %#"PRIx16,
                     flags);
        return OFPERR_OFPMOFC_BAD_FLAGS;
    }

    if (!is_all_zeros(nfmr->zeros, sizeof nfmr->zeros)) {
        return OFPERR_NXBRC_MUST_BE_ZERO;
    }

    rq->id = ntohl(nfmr->id);
    rq->flags = flags;
    rq->out_port = u16_to_ofp(ntohs(nfmr->out_port));
    rq->table_id = nfmr->table_id;

    return nx_pull_match(msg, ntohs(nfmr->match_len), &rq->match, NULL,
                         NULL, NULL, NULL);
}

Project: ovs
File: ofp-util.c

ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
                            const struct ofp_header *oh)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);
    if (raw == OFPRAW_OFPT11_FLOW_REMOVED) {
        const struct ofp12_flow_removed *ofr;
        enum ofperr error;

        ofr = ofpbuf_pull(&b, sizeof *ofr);

        error = ofputil_pull_ofp11_match(&b, NULL, NULL, &fr->match, NULL);
        if (error) {
            return error;
        }

        fr->priority = ntohs(ofr->priority);
        fr->cookie = ofr->cookie;
        fr->reason = ofr->reason;
        fr->table_id = ofr->table_id;
        fr->duration_sec = ntohl(ofr->duration_sec);
        fr->duration_nsec = ntohl(ofr->duration_nsec);
        fr->idle_timeout = ntohs(ofr->idle_timeout);
        fr->hard_timeout = ntohs(ofr->hard_timeout);
        fr->packet_count = ntohll(ofr->packet_count);
        fr->byte_count = ntohll(ofr->byte_count);
    } else if (raw == OFPRAW_OFPT10_FLOW_REMOVED) {
        const struct ofp10_flow_removed *ofr;

        ofr = ofpbuf_pull(&b, sizeof *ofr);

        ofputil_match_from_ofp10_match(&ofr->match, &fr->match);
        fr->priority = ntohs(ofr->priority);
        fr->cookie = ofr->cookie;
        fr->reason = ofr->reason;
        fr->table_id = 255;
        fr->duration_sec = ntohl(ofr->duration_sec);
        fr->duration_nsec = ntohl(ofr->duration_nsec);
        fr->idle_timeout = ntohs(ofr->idle_timeout);
        fr->hard_timeout = 0;
        fr->packet_count = ntohll(ofr->packet_count);
        fr->byte_count = ntohll(ofr->byte_count);
    } else if (raw == OFPRAW_NXT_FLOW_REMOVED) {
        struct nx_flow_removed *nfr;
        enum ofperr error;

        nfr = ofpbuf_pull(&b, sizeof *nfr);
        error = nx_pull_match(&b, ntohs(nfr->match_len), &fr->match, NULL,
                              NULL, NULL, NULL);
        if (error) {
            return error;
        }
        if (b.size) {
            return OFPERR_OFPBRC_BAD_LEN;
        }

        fr->priority = ntohs(nfr->priority);
        fr->cookie = nfr->cookie;
        fr->reason = nfr->reason;
        fr->table_id = nfr->table_id ? nfr->table_id - 1 : 255;
        fr->duration_sec = ntohl(nfr->duration_sec);
        fr->duration_nsec = ntohl(nfr->duration_nsec);
        fr->idle_timeout = ntohs(nfr->idle_timeout);
        fr->hard_timeout = 0;
        fr->packet_count = ntohll(nfr->packet_count);
        fr->byte_count = ntohll(nfr->byte_count);
    } else {
        OVS_NOT_REACHED();
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
                                struct ofpbuf *msg,
                                bool flow_age_extension,
                                struct ofpbuf *ofpacts)
{
    const struct ofp_header *oh;
    size_t instructions_len;
    enum ofperr error;
    enum ofpraw raw;

    error = (msg->header ? ofpraw_decode(&raw, msg->header)
             : ofpraw_pull(&raw, msg));
    if (error) {
        return error;
    }
    oh = msg->header;

    if (!msg->size) {
        return EOF;
    } else if (raw == OFPRAW_OFPST11_FLOW_REPLY
               || raw == OFPRAW_OFPST13_FLOW_REPLY) {
        const struct ofp11_flow_stats *ofs;
        size_t length;
        uint16_t padded_match_len;

        ofs = ofpbuf_try_pull(msg, sizeof *ofs);
        if (!ofs) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %"PRIu32" leftover "
                         "bytes at end", msg->size);
            return EINVAL;
        }

        length = ntohs(ofs->length);
        if (length < sizeof *ofs) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply claims invalid "
                         "length %"PRIuSIZE, length);
            return EINVAL;
        }

        if (ofputil_pull_ofp11_match(msg, NULL, NULL, &fs->match,
                                     &padded_match_len)) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad match");
            return EINVAL;
        }
        instructions_len = length - sizeof *ofs - padded_match_len;

        fs->priority = ntohs(ofs->priority);
        fs->table_id = ofs->table_id;
        fs->duration_sec = ntohl(ofs->duration_sec);
        fs->duration_nsec = ntohl(ofs->duration_nsec);
        fs->idle_timeout = ntohs(ofs->idle_timeout);
        fs->hard_timeout = ntohs(ofs->hard_timeout);
        if (oh->version >= OFP14_VERSION) {
            fs->importance = ntohs(ofs->importance);
        } else {
            fs->importance = 0;
        }
        if (raw == OFPRAW_OFPST13_FLOW_REPLY) {
            error = ofputil_decode_flow_mod_flags(ofs->flags, -1, oh->version,
                                                  &fs->flags);
            if (error) {
                return error;
            }
        } else {
            fs->flags = 0;
        }
        fs->idle_age = -1;
        fs->hard_age = -1;
        fs->cookie = ofs->cookie;
        fs->packet_count = ntohll(ofs->packet_count);
        fs->byte_count = ntohll(ofs->byte_count);
    } else if (raw == OFPRAW_OFPST10_FLOW_REPLY) {
        const struct ofp10_flow_stats *ofs;
        size_t length;

        ofs = ofpbuf_try_pull(msg, sizeof *ofs);
        if (!ofs) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %"PRIu32" leftover "
                         "bytes at end", msg->size);
            return EINVAL;
        }

        length = ntohs(ofs->length);
        if (length < sizeof *ofs) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply claims invalid "
                         "length %"PRIuSIZE, length);
            return EINVAL;
        }
        instructions_len = length - sizeof *ofs;

        fs->cookie = get_32aligned_be64(&ofs->cookie);
        ofputil_match_from_ofp10_match(&ofs->match, &fs->match);
        fs->priority = ntohs(ofs->priority);
        fs->table_id = ofs->table_id;
        fs->duration_sec = ntohl(ofs->duration_sec);
        fs->duration_nsec = ntohl(ofs->duration_nsec);
        fs->idle_timeout = ntohs(ofs->idle_timeout);
        fs->hard_timeout = ntohs(ofs->hard_timeout);
        fs->importance = 0;
        fs->idle_age = -1;
        fs->hard_age = -1;
        fs->packet_count = ntohll(get_32aligned_be64(&ofs->packet_count));
        fs->byte_count = ntohll(get_32aligned_be64(&ofs->byte_count));
        fs->flags = 0;
    } else if (raw == OFPRAW_NXST_FLOW_REPLY) {
        const struct nx_flow_stats *nfs;
        size_t match_len, length;

        nfs = ofpbuf_try_pull(msg, sizeof *nfs);
        if (!nfs) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW reply has %"PRIu32" leftover "
                         "bytes at end", msg->size);
            return EINVAL;
        }

        length = ntohs(nfs->length);
        match_len = ntohs(nfs->match_len);
        if (length < sizeof *nfs + ROUND_UP(match_len, 8)) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW reply with match_len=%"PRIuSIZE" "
                         "claims invalid length %"PRIuSIZE, match_len, length);
            return EINVAL;
        }
        if (nx_pull_match(msg, match_len, &fs->match, NULL, NULL, NULL,
                          NULL)) {
            return EINVAL;
        }
        instructions_len = length - sizeof *nfs - ROUND_UP(match_len, 8);

        fs->cookie = nfs->cookie;
        fs->table_id = nfs->table_id;
        fs->duration_sec = ntohl(nfs->duration_sec);
        fs->duration_nsec = ntohl(nfs->duration_nsec);
        fs->priority = ntohs(nfs->priority);
        fs->idle_timeout = ntohs(nfs->idle_timeout);
        fs->hard_timeout = ntohs(nfs->hard_timeout);
        fs->importance = 0;
        fs->idle_age = -1;
        fs->hard_age = -1;
        if (flow_age_extension) {
            if (nfs->idle_age) {
                fs->idle_age = ntohs(nfs->idle_age) - 1;
            }
            if (nfs->hard_age) {
                fs->hard_age = ntohs(nfs->hard_age) - 1;
            }
        }
        fs->packet_count = ntohll(nfs->packet_count);
        fs->byte_count = ntohll(nfs->byte_count);
        fs->flags = 0;
    } else {
        OVS_NOT_REACHED();
    }

    if (ofpacts_pull_openflow_instructions(msg, instructions_len, oh->version,
                                           NULL, NULL, ofpacts)) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad instructions");
        return EINVAL;
    }
    fs->ofpacts = ofpacts->data;
    fs->ofpacts_len = ofpacts->size;

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_flow_stats_request(struct ofputil_flow_stats_request *fsr,
                                  const struct ofp_header *oh,
                                  const struct tun_table *tun_table,
                                  const struct vl_mff_map *vl_mff_map)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);
    switch ((int) raw) {
    case OFPRAW_OFPST10_FLOW_REQUEST:
        return ofputil_decode_ofpst10_flow_request(fsr, b.data, false);

    case OFPRAW_OFPST10_AGGREGATE_REQUEST:
        return ofputil_decode_ofpst10_flow_request(fsr, b.data, true);

    case OFPRAW_OFPST11_FLOW_REQUEST:
        return ofputil_decode_ofpst11_flow_request(fsr, &b, false, tun_table,
                                                   vl_mff_map);

    case OFPRAW_OFPST11_AGGREGATE_REQUEST:
        return ofputil_decode_ofpst11_flow_request(fsr, &b, true, tun_table,
                                                   vl_mff_map);

    case OFPRAW_NXST_FLOW_REQUEST:
        return ofputil_decode_nxst_flow_request(fsr, &b, false, tun_table,
                                                vl_mff_map);

    case OFPRAW_NXST_AGGREGATE_REQUEST:
        return ofputil_decode_nxst_flow_request(fsr, &b, true, tun_table,
                                                vl_mff_map);

    default:
        /* Hey, the caller lied. */
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_decode_flow_update(struct ofputil_flow_update *update,
                           struct ofpbuf *msg, struct ofpbuf *ofpacts)
{
    struct nx_flow_update_header *nfuh;
    unsigned int length;
    struct ofp_header *oh;

    if (!msg->header) {
        ofpraw_pull_assert(msg);
    }

    ofpbuf_clear(ofpacts);
    if (!msg->size) {
        return EOF;
    }

    if (msg->size < sizeof(struct nx_flow_update_header)) {
        goto bad_len;
    }

    oh = msg->header;

    nfuh = msg->data;
    update->event = ntohs(nfuh->event);
    length = ntohs(nfuh->length);
    if (length > msg->size || length % 8) {
        goto bad_len;
    }

    if (update->event == NXFME_ABBREV) {
        struct nx_flow_update_abbrev *nfua;

        if (length != sizeof *nfua) {
            goto bad_len;
        }

        nfua = ofpbuf_pull(msg, sizeof *nfua);
        update->xid = nfua->xid;
        return 0;
    } else if (update->event == NXFME_ADDED
               || update->event == NXFME_DELETED
               || update->event == NXFME_MODIFIED) {
        struct nx_flow_update_full *nfuf;
        unsigned int actions_len;
        unsigned int match_len;
        enum ofperr error;

        if (length < sizeof *nfuf) {
            goto bad_len;
        }

        nfuf = ofpbuf_pull(msg, sizeof *nfuf);
        match_len = ntohs(nfuf->match_len);
        if (sizeof *nfuf + match_len > length) {
            goto bad_len;
        }

        update->reason = ntohs(nfuf->reason);
        update->idle_timeout = ntohs(nfuf->idle_timeout);
        update->hard_timeout = ntohs(nfuf->hard_timeout);
        update->table_id = nfuf->table_id;
        update->cookie = nfuf->cookie;
        update->priority = ntohs(nfuf->priority);

        error = nx_pull_match(msg, match_len, &update->match, NULL, NULL, NULL,
                              NULL);
        if (error) {
            return error;
        }

        actions_len = length - sizeof *nfuf - ROUND_UP(match_len, 8);
        error = ofpacts_pull_openflow_actions(msg, actions_len, oh->version,
                                              NULL, NULL, ofpacts);
        if (error) {
            return error;
        }

        update->ofpacts = ofpacts->data;
        update->ofpacts_len = ofpacts->size;
        return 0;
    } else {
        VLOG_WARN_RL(&bad_ofmsg_rl,
                     "NXST_FLOW_MONITOR reply has bad event %"PRIu16,
                     ntohs(nfuh->event));
        return OFPERR_NXBRC_FM_BAD_EVENT;
    }

bad_len:
    VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR reply has %"PRIu32" "
                 "leftover bytes at end", msg->size);
    return OFPERR_OFPBRC_BAD_LEN;
}

Project: ovs
File: ofp-util.c

ofputil_decode_get_config_reply(const struct ofp_header *oh,
                                struct ofputil_switch_config *config)
{
    ofputil_decode_switch_config(oh, config);
}

Project: ovs
File: ofp-util.c

ofputil_decode_group_desc_reply(struct ofputil_group_desc *gd,
                                struct ofpbuf *msg, enum ofp_version version)
{
    ofputil_init_group_properties(&gd->props);

    switch (version)
    {
    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION:
    case OFP14_VERSION:
        return ofputil_decode_ofp11_group_desc_reply(gd, msg, version);

    case OFP15_VERSION:
    case OFP16_VERSION:
        return ofputil_decode_ofp15_group_desc_reply(gd, msg, version);

    case OFP10_VERSION:
    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_decode_group_desc_request(const struct ofp_header *oh)
{
    struct ofpbuf request = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&request);
    if (raw == OFPRAW_OFPST11_GROUP_DESC_REQUEST) {
        return OFPG_ALL;
    } else if (raw == OFPRAW_OFPST15_GROUP_DESC_REQUEST) {
        ovs_be32 *group_id = ofpbuf_pull(&request, sizeof *group_id);
        return ntohl(*group_id);
    } else {
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_decode_group_features_reply(const struct ofp_header *oh,
                                    struct ofputil_group_features *features)
{
    const struct ofp12_group_features_stats *ogf = ofpmsg_body(oh);
    int i;

    features->types = ntohl(ogf->types);
    features->capabilities = ntohl(ogf->capabilities);
    for (i = 0; i < OFPGT12_N_TYPES; i++) {
        features->max_groups[i] = ntohl(ogf->max_groups[i]);
        features->ofpacts[i] = ofpact_bitmap_from_openflow(
            ogf->actions[i], oh->version);
    }
}

Project: ovs
File: ofp-util.c

ofputil_decode_group_mod(const struct ofp_header *oh,
                         struct ofputil_group_mod *gm)
{
    ofputil_init_group_properties(&gm->props);

    enum ofp_version ofp_version = oh->version;
    struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
    ofpraw_pull_assert(&msg);

    enum ofperr err;
    switch (ofp_version)
    {
    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION:
    case OFP14_VERSION:
        err = ofputil_pull_ofp11_group_mod(&msg, ofp_version, gm);
        break;

    case OFP15_VERSION:
    case OFP16_VERSION:
        err = ofputil_pull_ofp15_group_mod(&msg, ofp_version, gm);
        break;

    case OFP10_VERSION:
    default:
        OVS_NOT_REACHED();
    }
    if (err) {
        return err;
    }

    err = ofputil_check_group_mod(gm);
    if (err) {
        ofputil_uninit_group_mod(gm);
    }
    return err;
}

Project: ovs
File: ofp-util.c

ofputil_decode_group_stats_reply(struct ofpbuf *msg,
                                 struct ofputil_group_stats *gs)
{
    struct ofp11_bucket_counter *obc;
    struct ofp11_group_stats *ogs11;
    enum ofpraw raw;
    enum ofperr error;
    size_t base_len;
    size_t length;
    size_t i;

    gs->bucket_stats = NULL;
    error = (msg->header ? ofpraw_decode(&raw, msg->header)
             : ofpraw_pull(&raw, msg));
    if (error) {
        return error;
    }

    if (!msg->size) {
        return EOF;
    }

    if (raw == OFPRAW_OFPST11_GROUP_REPLY) {
        base_len = sizeof *ogs11;
        ogs11 = ofpbuf_try_pull(msg, sizeof *ogs11);
        gs->duration_sec = gs->duration_nsec = UINT32_MAX;
    } else if (raw == OFPRAW_OFPST13_GROUP_REPLY) {
        struct ofp13_group_stats *ogs13;

        base_len = sizeof *ogs13;
        ogs13 = ofpbuf_try_pull(msg, sizeof *ogs13);
        if (ogs13) {
            ogs11 = &ogs13->gs;
            gs->duration_sec = ntohl(ogs13->duration_sec);
            gs->duration_nsec = ntohl(ogs13->duration_nsec);
        } else {
            ogs11 = NULL;
        }
    } else {
        OVS_NOT_REACHED();
    }

    if (!ogs11) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %"PRIu32" leftover bytes at end",
                     ofpraw_get_name(raw), msg->size);
        return OFPERR_OFPBRC_BAD_LEN;
    }
    length = ntohs(ogs11->length);
    if (length < sizeof base_len) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply claims invalid length %"PRIuSIZE,
                     ofpraw_get_name(raw), length);
        return OFPERR_OFPBRC_BAD_LEN;
    }

    gs->group_id = ntohl(ogs11->group_id);
    gs->ref_count = ntohl(ogs11->ref_count);
    gs->packet_count = ntohll(ogs11->packet_count);
    gs->byte_count = ntohll(ogs11->byte_count);

    gs->n_buckets = (length - base_len) / sizeof *obc;
    obc = ofpbuf_try_pull(msg, gs->n_buckets * sizeof *obc);
    if (!obc) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %"PRIu32" leftover bytes at end",
                     ofpraw_get_name(raw), msg->size);
        return OFPERR_OFPBRC_BAD_LEN;
    }

    gs->bucket_stats = xmalloc(gs->n_buckets * sizeof *gs->bucket_stats);
    for (i = 0; i < gs->n_buckets; i++) {
        gs->bucket_stats[i].packet_count = ntohll(obc[i].packet_count);
        gs->bucket_stats[i].byte_count = ntohll(obc[i].byte_count);
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_group_stats_request(const struct ofp_header *request,
                                   uint32_t *group_id)
{
    const struct ofp11_group_stats_request *gsr11 = ofpmsg_body(request);
    *group_id = ntohl(gsr11->group_id);
    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_hello(const struct ofp_header *oh, uint32_t *allowed_versions)
{
    struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
    ofpbuf_pull(&msg, sizeof *oh);

    *allowed_versions = version_bitmap_from_version(oh->version);

    bool ok = true;
    while (msg.size) {
        const struct ofp_hello_elem_header *oheh;
        unsigned int len;

        if (msg.size < sizeof *oheh) {
            return false;
        }

        oheh = msg.data;
        len = ntohs(oheh->length);
        if (len < sizeof *oheh || !ofpbuf_try_pull(&msg, ROUND_UP(len, 8))) {
            return false;
        }

        if (oheh->type != htons(OFPHET_VERSIONBITMAP)
            || !ofputil_decode_hello_bitmap(oheh, allowed_versions)) {
            ok = false;
        }
    }

    return ok;
}

Project: ovs
File: ofp-util.c

ofputil_decode_hello_bitmap(const struct ofp_hello_elem_header *oheh,
                            uint32_t *allowed_versionsp)
{
    uint16_t bitmap_len = ntohs(oheh->length) - sizeof *oheh;
    const ovs_be32 *bitmap = ALIGNED_CAST(const ovs_be32 *, oheh + 1);
    uint32_t allowed_versions;

    if (!bitmap_len || bitmap_len % sizeof *bitmap) {
        return false;
    }

    /* Only use the first 32-bit element of the bitmap as that is all the
     * current implementation supports.  Subsequent elements are ignored which
     * should have no effect on session negotiation until Open vSwitch supports
     * wire-protocol versions greater than 31.
     */
    allowed_versions = ntohl(bitmap[0]);

    if (allowed_versions & 1) {
        /* There's no OpenFlow version 0. */
        VLOG_WARN_RL(&bad_ofmsg_rl, "peer claims to support invalid OpenFlow "
                     "version 0x00");
        allowed_versions &= ~1u;
    }

    if (!allowed_versions) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "peer does not support any OpenFlow "
                     "version (between 0x01 and 0x1f)");
        return false;
    }

    *allowed_versionsp = allowed_versions;
    return true;
}

Project: ovs
File: ofp-util.c

ofputil_decode_meter_config(struct ofpbuf *msg,
                            struct ofputil_meter_config *mc,
                            struct ofpbuf *bands)
{
    const struct ofp13_meter_config *omc;
    enum ofperr err;

    /* Pull OpenFlow headers for the first call. */
    if (!msg->header) {
        ofpraw_pull_assert(msg);
    }

    if (!msg->size) {
        return EOF;
    }

    omc = ofpbuf_try_pull(msg, sizeof *omc);
    if (!omc) {
        VLOG_WARN_RL(&bad_ofmsg_rl,
                     "OFPMP_METER_CONFIG reply has %"PRIu32" leftover bytes at end",
                     msg->size);
        return OFPERR_OFPBRC_BAD_LEN;
    }

    ofpbuf_clear(bands);
    err = ofputil_pull_bands(msg, ntohs(omc->length) - sizeof *omc,
                             &mc->n_bands, bands);
    if (err) {
        return err;
    }
    mc->meter_id = ntohl(omc->meter_id);
    mc->flags = ntohs(omc->flags);
    mc->bands = bands->data;

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_meter_features(const struct ofp_header *oh,
                              struct ofputil_meter_features *mf)
{
    const struct ofp13_meter_features *omf = ofpmsg_body(oh);

    mf->max_meters = ntohl(omf->max_meter);
    mf->band_types = ntohl(omf->band_types);
    mf->capabilities = ntohl(omf->capabilities);
    mf->max_bands = omf->max_bands;
    mf->max_color = omf->max_color;
}

Project: ovs
File: ofp-util.c

ofputil_decode_meter_mod(const struct ofp_header *oh,
                         struct ofputil_meter_mod *mm,
                         struct ofpbuf *bands)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    ofpraw_pull_assert(&b);
    const struct ofp13_meter_mod *omm = ofpbuf_pull(&b, sizeof *omm);

    /* Translate the message. */
    mm->command = ntohs(omm->command);
    if (mm->command != OFPMC13_ADD &&
        mm->command != OFPMC13_MODIFY &&
        mm->command != OFPMC13_DELETE) {
        return OFPERR_OFPMMFC_BAD_COMMAND;
    }
    mm->meter.meter_id = ntohl(omm->meter_id);

    if (mm->command == OFPMC13_DELETE) {
        mm->meter.flags = 0;
        mm->meter.n_bands = 0;
        mm->meter.bands = NULL;
    } else {
        enum ofperr error;

        mm->meter.flags = ntohs(omm->flags);
        if (mm->meter.flags & OFPMF13_KBPS &&
            mm->meter.flags & OFPMF13_PKTPS) {
            return OFPERR_OFPMMFC_BAD_FLAGS;
        }

        error = ofputil_pull_bands(&b, b.size, &mm->meter.n_bands, bands);
        if (error) {
            return error;
        }
        mm->meter.bands = bands->data;
    }
    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_meter_request(const struct ofp_header *oh, uint32_t *meter_id)
{
    const struct ofp13_meter_multipart_request *omr = ofpmsg_body(oh);
    *meter_id = ntohl(omr->meter_id);
}

Project: ovs
File: ofp-util.c

ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr,
                                 struct ofpbuf *b, bool aggregate,
                                 const struct tun_table *tun_table,
                                 const struct vl_mff_map *vl_mff_map)
{
    const struct nx_flow_stats_request *nfsr;
    enum ofperr error;

    nfsr = ofpbuf_pull(b, sizeof *nfsr);
    error = nx_pull_match(b, ntohs(nfsr->match_len), &fsr->match,
                          &fsr->cookie, &fsr->cookie_mask, tun_table,
                          vl_mff_map);
    if (error) {
        return error;
    }
    if (b->size) {
        return OFPERR_OFPBRC_BAD_LEN;
    }

    fsr->aggregate = aggregate;
    fsr->out_port = u16_to_ofp(ntohs(nfsr->out_port));
    fsr->out_group = OFPG_ANY;
    fsr->table_id = nfsr->table_id;

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_ofp10_phy_port(struct ofputil_phy_port *pp,
                              const struct ofp10_phy_port *opp)
{
    pp->port_no = u16_to_ofp(ntohs(opp->port_no));
    pp->hw_addr = opp->hw_addr;
    ovs_strlcpy(pp->name, opp->name, OFP_MAX_PORT_NAME_LEN);

    pp->config = ntohl(opp->config) & OFPPC10_ALL;
    pp->state = ntohl(opp->state) & OFPPS10_ALL;

    pp->curr = netdev_port_features_from_ofp10(opp->curr);
    pp->advertised = netdev_port_features_from_ofp10(opp->advertised);
    pp->supported = netdev_port_features_from_ofp10(opp->supported);
    pp->peer = netdev_port_features_from_ofp10(opp->peer);

    pp->curr_speed = netdev_features_to_bps(pp->curr, 0) / 1000;
    pp->max_speed = netdev_features_to_bps(pp->supported, 0) / 1000;

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_ofp10_table_stats(struct ofpbuf *msg,
                                 struct ofputil_table_stats *stats,
                                 struct ofputil_table_features *features)
{
    struct ofp10_table_stats *ots;

    ots = ofpbuf_try_pull(msg, sizeof *ots);
    if (!ots) {
        return OFPERR_OFPBRC_BAD_LEN;
    }

    features->table_id = ots->table_id;
    ovs_strlcpy(features->name, ots->name, sizeof features->name);
    features->max_entries = ntohl(ots->max_entries);
    features->match = features->wildcard = mf_bitmap_from_of10(ots->wildcards);

    stats->table_id = ots->table_id;
    stats->active_count = ntohl(ots->active_count);
    stats->lookup_count = ntohll(get_32aligned_be64(&ots->lookup_count));
    stats->matched_count = ntohll(get_32aligned_be64(&ots->matched_count));

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_ofp11_group_desc_reply(struct ofputil_group_desc *gd,
                                      struct ofpbuf *msg,
                                      enum ofp_version version)
{
    struct ofp11_group_desc_stats *ogds;
    size_t length;

    if (!msg->header) {
        ofpraw_pull_assert(msg);
    }

    if (!msg->size) {
        return EOF;
    }

    ogds = ofpbuf_try_pull(msg, sizeof *ogds);
    if (!ogds) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply has %"PRIu32" "
                     "leftover bytes at end", msg->size);
        return OFPERR_OFPBRC_BAD_LEN;
    }
    gd->type = ogds->type;
    gd->group_id = ntohl(ogds->group_id);

    length = ntohs(ogds->length);
    if (length < sizeof *ogds || length - sizeof *ogds > msg->size) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply claims invalid "
                     "length %"PRIuSIZE, length);
        return OFPERR_OFPBRC_BAD_LEN;
    }

    return ofputil_pull_ofp11_buckets(msg, length - sizeof *ogds, version,
                                      &gd->buckets);
}

Project: ovs
File: ofp-util.c

ofputil_decode_ofp11_port(struct ofputil_phy_port *pp,
                          const struct ofp11_port *op)
{
    enum ofperr error;

    error = ofputil_port_from_ofp11(op->port_no, &pp->port_no);
    if (error) {
        return error;
    }
    pp->hw_addr = op->hw_addr;
    ovs_strlcpy(pp->name, op->name, OFP_MAX_PORT_NAME_LEN);

    pp->config = ntohl(op->config) & OFPPC11_ALL;
    pp->state = ntohl(op->state) & OFPPS11_ALL;

    pp->curr = netdev_port_features_from_ofp11(op->curr);
    pp->advertised = netdev_port_features_from_ofp11(op->advertised);
    pp->supported = netdev_port_features_from_ofp11(op->supported);
    pp->peer = netdev_port_features_from_ofp11(op->peer);

    pp->curr_speed = ntohl(op->curr_speed);
    pp->max_speed = ntohl(op->max_speed);

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_ofp11_table_stats(struct ofpbuf *msg,
                                 struct ofputil_table_stats *stats,
                                 struct ofputil_table_features *features)
{
    struct ofp11_table_stats *ots;

    ots = ofpbuf_try_pull(msg, sizeof *ots);
    if (!ots) {
        return OFPERR_OFPBRC_BAD_LEN;
    }

    features->table_id = ots->table_id;
    ovs_strlcpy(features->name, ots->name, sizeof features->name);
    features->max_entries = ntohl(ots->max_entries);
    features->nonmiss.instructions = ovsinst_bitmap_from_openflow(
        ots->instructions, OFP11_VERSION);
    features->nonmiss.write.ofpacts = ofpact_bitmap_from_openflow(
        ots->write_actions, OFP11_VERSION);
    features->nonmiss.apply.ofpacts = ofpact_bitmap_from_openflow(
        ots->write_actions, OFP11_VERSION);
    features->miss = features->nonmiss;
    features->miss_config = ofputil_decode_table_miss(ots->config,
                                                      OFP11_VERSION);
    features->match = mf_bitmap_from_of11(ots->match);
    features->wildcard = mf_bitmap_from_of11(ots->wildcards);
    bitmap_or(features->match.bm, features->wildcard.bm, MFF_N_IDS);

    stats->table_id = ots->table_id;
    stats->active_count = ntohl(ots->active_count);
    stats->lookup_count = ntohll(ots->lookup_count);
    stats->matched_count = ntohll(ots->matched_count);

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_ofp12_table_stats(struct ofpbuf *msg,
                                 struct ofputil_table_stats *stats,
                                 struct ofputil_table_features *features)
{
    struct ofp12_table_stats *ots;

    ots = ofpbuf_try_pull(msg, sizeof *ots);
    if (!ots) {
        return OFPERR_OFPBRC_BAD_LEN;
    }

    features->table_id = ots->table_id;
    ovs_strlcpy(features->name, ots->name, sizeof features->name);
    features->metadata_match = ots->metadata_match;
    features->metadata_write = ots->metadata_write;
    features->miss_config = ofputil_decode_table_miss(ots->config,
                                                      OFP12_VERSION);
    features->max_entries = ntohl(ots->max_entries);

    features->nonmiss.instructions = ovsinst_bitmap_from_openflow(
        ots->instructions, OFP12_VERSION);
    features->nonmiss.write.ofpacts = ofpact_bitmap_from_openflow(
        ots->write_actions, OFP12_VERSION);
    features->nonmiss.apply.ofpacts = ofpact_bitmap_from_openflow(
        ots->apply_actions, OFP12_VERSION);
    features->nonmiss.write.set_fields = oxm_bitmap_to_mf_bitmap(
        ots->write_setfields, OFP12_VERSION);
    features->nonmiss.apply.set_fields = oxm_bitmap_to_mf_bitmap(
        ots->apply_setfields, OFP12_VERSION);
    features->miss = features->nonmiss;

    features->match = oxm_bitmap_to_mf_bitmap(ots->match, OFP12_VERSION);
    features->wildcard = oxm_bitmap_to_mf_bitmap(ots->wildcards,
                                                 OFP12_VERSION);
    bitmap_or(features->match.bm, features->wildcard.bm, MFF_N_IDS);

    stats->table_id = ots->table_id;
    stats->active_count = ntohl(ots->active_count);
    stats->lookup_count = ntohll(ots->lookup_count);
    stats->matched_count = ntohll(ots->matched_count);

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_ofp13_table_stats(struct ofpbuf *msg,
                                 struct ofputil_table_stats *stats,
                                 struct ofputil_table_features *features)
{
    struct ofp13_table_stats *ots;

    ots = ofpbuf_try_pull(msg, sizeof *ots);
    if (!ots) {
        return OFPERR_OFPBRC_BAD_LEN;
    }

    features->table_id = ots->table_id;

    stats->table_id = ots->table_id;
    stats->active_count = ntohl(ots->active_count);
    stats->lookup_count = ntohll(ots->lookup_count);
    stats->matched_count = ntohll(ots->matched_count);

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_ofp15_group_desc_reply(struct ofputil_group_desc *gd,
                                      struct ofpbuf *msg,
                                      enum ofp_version version)
{
    struct ofp15_group_desc_stats *ogds;
    uint16_t length, bucket_list_len;
    int error;

    if (!msg->header) {
        ofpraw_pull_assert(msg);
    }

    if (!msg->size) {
        return EOF;
    }

    ogds = ofpbuf_try_pull(msg, sizeof *ogds);
    if (!ogds) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply has %"PRIu32" "
                     "leftover bytes at end", msg->size);
        return OFPERR_OFPBRC_BAD_LEN;
    }
    gd->type = ogds->type;
    gd->group_id = ntohl(ogds->group_id);

    length = ntohs(ogds->length);
    if (length < sizeof *ogds || length - sizeof *ogds > msg->size) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply claims invalid "
                     "length %u", length);
        return OFPERR_OFPBRC_BAD_LEN;
    }

    bucket_list_len = ntohs(ogds->bucket_list_len);
    if (length < bucket_list_len + sizeof *ogds) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply claims invalid "
                     "bucket list length %u", bucket_list_len);
        return OFPERR_OFPBRC_BAD_LEN;
    }
    error = ofputil_pull_ofp15_buckets(msg, bucket_list_len, version, gd->type,
                                       &gd->buckets);
    if (error) {
        return error;
    }

    /* By definition group desc messages don't have a group mod command.
     * However, parse_group_prop_ntr_selection_method() checks to make sure
     * that the command is OFPGC15_ADD or OFPGC15_DELETE to guard
     * against group mod messages with other commands supplying
     * a NTR selection method group experimenter property.
     * Such properties are valid for group desc replies so
     * claim that the group mod command is OFPGC15_ADD to
     * satisfy the check in parse_group_prop_ntr_selection_method() */
    error = parse_ofp15_group_properties(
        msg, gd->type, OFPGC15_ADD, &gd->props,
        length - sizeof *ogds - bucket_list_len);
    if (error) {
        ofputil_bucket_list_destroy(&gd->buckets);
    }
    return error;
}

Project: ovs
File: ofp-util.c

ofputil_decode_ofpst10_flow_request(struct ofputil_flow_stats_request *fsr,
                                    const struct ofp10_flow_stats_request *ofsr,
                                    bool aggregate)
{
    fsr->aggregate = aggregate;
    ofputil_match_from_ofp10_match(&ofsr->match, &fsr->match);
    fsr->out_port = u16_to_ofp(ntohs(ofsr->out_port));
    fsr->out_group = OFPG_ANY;
    fsr->table_id = ofsr->table_id;
    fsr->cookie = fsr->cookie_mask = htonll(0);

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_ofpst11_flow_request(struct ofputil_flow_stats_request *fsr,
                                    struct ofpbuf *b, bool aggregate,
                                    const struct tun_table *tun_table,
                                    const struct vl_mff_map *vl_mff_map)
{
    const struct ofp11_flow_stats_request *ofsr;
    enum ofperr error;

    ofsr = ofpbuf_pull(b, sizeof *ofsr);
    fsr->aggregate = aggregate;
    fsr->table_id = ofsr->table_id;
    error = ofputil_port_from_ofp11(ofsr->out_port, &fsr->out_port);
    if (error) {
        return error;
    }
    fsr->out_group = ntohl(ofsr->out_group);
    fsr->cookie = ofsr->cookie;
    fsr->cookie_mask = ofsr->cookie_mask;
    error = ofputil_pull_ofp11_match(b, tun_table, vl_mff_map, &fsr->match,
                                     NULL);
    if (error) {
        return error;
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_packet_in(const struct ofp_header *oh, bool loose,
                         const struct tun_table *tun_table,
                         const struct vl_mff_map *vl_mff_map,
                         struct ofputil_packet_in *pin,
                         size_t *total_lenp, uint32_t *buffer_idp,
                         struct ofpbuf *continuation)
{
    uint32_t buffer_id;
    size_t total_len;

    memset(pin, 0, sizeof *pin);
    pin->cookie = OVS_BE64_MAX;
    if (continuation) {
        ofpbuf_use_const(continuation, NULL, 0);
    }

    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);
    if (raw == OFPRAW_OFPT13_PACKET_IN || raw == OFPRAW_OFPT12_PACKET_IN) {
        const struct ofp12_packet_in *opi = ofpbuf_pull(&b, sizeof *opi);
        const ovs_be64 *cookie = (raw == OFPRAW_OFPT13_PACKET_IN
                                  ? ofpbuf_pull(&b, sizeof *cookie)
                                  : NULL);
        enum ofperr error = oxm_pull_match_loose(&b, tun_table,
                                                 &pin->flow_metadata);
        if (error) {
            return error;
        }

        if (!ofpbuf_try_pull(&b, 2)) {
            return OFPERR_OFPBRC_BAD_LEN;
        }

        pin->reason = opi->reason;
        pin->table_id = opi->table_id;
        buffer_id = ntohl(opi->buffer_id);
        total_len = ntohs(opi->total_len);
        if (cookie) {
            pin->cookie = *cookie;
        }

        pin->packet = b.data;
        pin->packet_len = b.size;
    } else if (raw == OFPRAW_OFPT10_PACKET_IN) {
        const struct ofp10_packet_in *opi;

        opi = ofpbuf_pull(&b, offsetof(struct ofp10_packet_in, data));

        pin->packet = CONST_CAST(uint8_t *, opi->data);
        pin->packet_len = b.size;

        match_init_catchall(&pin->flow_metadata);
        match_set_in_port(&pin->flow_metadata,
                          u16_to_ofp(ntohs(opi->in_port)));
        pin->reason = opi->reason;
        buffer_id = ntohl(opi->buffer_id);
        total_len = ntohs(opi->total_len);
    } else if (raw == OFPRAW_OFPT11_PACKET_IN) {
        const struct ofp11_packet_in *opi;
        ofp_port_t in_port;
        enum ofperr error;

        opi = ofpbuf_pull(&b, sizeof *opi);

        pin->packet = b.data;
        pin->packet_len = b.size;

        buffer_id = ntohl(opi->buffer_id);
        error = ofputil_port_from_ofp11(opi->in_port, &in_port);
        if (error) {
            return error;
        }
        match_init_catchall(&pin->flow_metadata);
        match_set_in_port(&pin->flow_metadata, in_port);
        total_len = ntohs(opi->total_len);
        pin->reason = opi->reason;
        pin->table_id = opi->table_id;
    } else if (raw == OFPRAW_NXT_PACKET_IN) {
        const struct nx_packet_in *npi;
        int error;

        npi = ofpbuf_pull(&b, sizeof *npi);
        error = nx_pull_match_loose(&b, ntohs(npi->match_len),
                                    &pin->flow_metadata, NULL, NULL, NULL);
        if (error) {
            return error;
        }

        if (!ofpbuf_try_pull(&b, 2)) {
            return OFPERR_OFPBRC_BAD_LEN;
        }

        pin->reason = npi->reason;
        pin->table_id = npi->table_id;
        pin->cookie = npi->cookie;

        buffer_id = ntohl(npi->buffer_id);
        total_len = ntohs(npi->total_len);

        pin->packet = b.data;
        pin->packet_len = b.size;
    } else if (raw == OFPRAW_NXT_PACKET_IN2 || raw == OFPRAW_NXT_RESUME) {
        enum ofperr error = decode_nx_packet_in2(oh, loose, tun_table,
                                                 vl_mff_map, pin, &total_len,
                                                 &buffer_id, continuation);
        if (error) {
            return error;
        }
    } else {
        OVS_NOT_REACHED();
    }

    if (total_lenp) {
        *total_lenp = total_len;
    }
    if (buffer_idp) {
        *buffer_idp = buffer_id;
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_packet_in_private(const struct ofp_header *oh, bool loose,
                                 const struct tun_table *tun_table,
                                 const struct vl_mff_map *vl_mff_map,
                                 struct ofputil_packet_in_private *pin,
                                 size_t *total_len, uint32_t *buffer_id)
{
    memset(pin, 0, sizeof *pin);

    struct ofpbuf continuation;
    enum ofperr error;
    error = ofputil_decode_packet_in(oh, loose, tun_table, vl_mff_map,
                                     &pin->public, total_len, buffer_id,
                                     &continuation);
    if (error) {
        return error;
    }

    struct ofpbuf actions, action_set;
    ofpbuf_init(&actions, 0);
    ofpbuf_init(&action_set, 0);

    uint8_t table_id = 0;
    ovs_be64 cookie = 0;

    struct ofpbuf stack;
    ofpbuf_init(&stack, 0);

    while (continuation.size > 0) {
        struct ofpbuf payload;
        uint64_t type;

        error = ofpprop_pull(&continuation, &payload, &type);
        if (error) {
            break;
        }

        switch (type) {
        case NXCPT_BRIDGE:
            error = ofpprop_parse_uuid(&payload, &pin->bridge);
            break;

        case NXCPT_STACK:
            error = parse_stack_prop(&payload, &stack);
            break;

        case NXCPT_MIRRORS:
            error = ofpprop_parse_u32(&payload, &pin->mirrors);
            break;

        case NXCPT_CONNTRACKED:
            pin->conntracked = true;
            break;

        case NXCPT_TABLE_ID:
            error = ofpprop_parse_u8(&payload, &table_id);
            break;

        case NXCPT_COOKIE:
            error = ofpprop_parse_be64(&payload, &cookie);
            break;

        case NXCPT_ACTIONS: {
            struct ofpact_unroll_xlate *unroll
                = ofpact_put_UNROLL_XLATE(&actions);
            unroll->rule_table_id = table_id;
            unroll->rule_cookie = cookie;
            error = parse_actions_property(&payload, oh->version, &actions);
            break;
        }

        case NXCPT_ACTION_SET:
            error = parse_actions_property(&payload, oh->version, &action_set);
            break;

        default:
            error = OFPPROP_UNKNOWN(loose, "continuation", type);
            break;
        }
        if (error) {
            break;
        }
    }

    pin->actions_len = actions.size;
    pin->actions = ofpbuf_steal_data(&actions);
    pin->action_set_len = action_set.size;
    pin->action_set = ofpbuf_steal_data(&action_set);
    pin->stack_size = stack.size;
    pin->stack = ofpbuf_steal_data(&stack);

    if (error) {
        ofputil_packet_in_private_destroy(pin);
    }

    return error;
}

Project: ovs
File: ofp-util.c

ofputil_decode_packet_out(struct ofputil_packet_out *po,
                          const struct ofp_header *oh,
                          struct ofpbuf *ofpacts)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);

    ofpbuf_clear(ofpacts);
    if (raw == OFPRAW_OFPT11_PACKET_OUT) {
        enum ofperr error;
        const struct ofp11_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);

        po->buffer_id = ntohl(opo->buffer_id);
        error = ofputil_port_from_ofp11(opo->in_port, &po->in_port);
        if (error) {
            return error;
        }

        error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
                                              oh->version, NULL, NULL,
                                              ofpacts);
        if (error) {
            return error;
        }
    } else if (raw == OFPRAW_OFPT10_PACKET_OUT) {
        enum ofperr error;
        const struct ofp10_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);

        po->buffer_id = ntohl(opo->buffer_id);
        po->in_port = u16_to_ofp(ntohs(opo->in_port));

        error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
                                              oh->version, NULL, NULL,
                                              ofpacts);
        if (error) {
            return error;
        }
    } else {
        OVS_NOT_REACHED();
    }

    if (ofp_to_u16(po->in_port) >= ofp_to_u16(OFPP_MAX)
        && po->in_port != OFPP_LOCAL
        && po->in_port != OFPP_NONE && po->in_port != OFPP_CONTROLLER) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out has bad input port %#"PRIx32,
                     po->in_port);
        return OFPERR_OFPBRC_BAD_PORT;
    }

    po->ofpacts = ofpacts->data;
    po->ofpacts_len = ofpacts->size;

    if (po->buffer_id == UINT32_MAX) {
        po->packet = b.data;
        po->packet_len = b.size;
    } else {
        po->packet = NULL;
        po->packet_len = 0;
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_port_desc_stats_request(const struct ofp_header *request,
                                       ofp_port_t *port)
{
    struct ofpbuf b = ofpbuf_const_initializer(request,
                                               ntohs(request->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);
    if (raw == OFPRAW_OFPST10_PORT_DESC_REQUEST) {
        *port = OFPP_ANY;
        return 0;
    } else if (raw == OFPRAW_OFPST15_PORT_DESC_REQUEST) {
        ovs_be32 *ofp11_port;

        ofp11_port = ofpbuf_pull(&b, sizeof *ofp11_port);
        return ofputil_port_from_ofp11(*ofp11_port, port);
    } else {
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_decode_port_mod(const struct ofp_header *oh,
                        struct ofputil_port_mod *pm, bool loose)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);
    if (raw == OFPRAW_OFPT10_PORT_MOD) {
        const struct ofp10_port_mod *opm = b.data;

        pm->port_no = u16_to_ofp(ntohs(opm->port_no));
        pm->hw_addr = opm->hw_addr;
        pm->config = ntohl(opm->config) & OFPPC10_ALL;
        pm->mask = ntohl(opm->mask) & OFPPC10_ALL;
        pm->advertise = netdev_port_features_from_ofp10(opm->advertise);
    } else if (raw == OFPRAW_OFPT11_PORT_MOD) {
        const struct ofp11_port_mod *opm = b.data;
        enum ofperr error;

        error = ofputil_port_from_ofp11(opm->port_no, &pm->port_no);
        if (error) {
            return error;
        }

        pm->hw_addr = opm->hw_addr;
        pm->config = ntohl(opm->config) & OFPPC11_ALL;
        pm->mask = ntohl(opm->mask) & OFPPC11_ALL;
        pm->advertise = netdev_port_features_from_ofp11(opm->advertise);
    } else if (raw == OFPRAW_OFPT14_PORT_MOD) {
        const struct ofp14_port_mod *opm = ofpbuf_pull(&b, sizeof *opm);
        enum ofperr error;

        memset(pm, 0, sizeof *pm);

        error = ofputil_port_from_ofp11(opm->port_no, &pm->port_no);
        if (error) {
            return error;
        }

        pm->hw_addr = opm->hw_addr;
        pm->config = ntohl(opm->config) & OFPPC11_ALL;
        pm->mask = ntohl(opm->mask) & OFPPC11_ALL;

        while (b.size > 0) {
            struct ofpbuf property;
            enum ofperr error;
            uint64_t type;

            error = ofpprop_pull(&b, &property, &type);
            if (error) {
                return error;
            }

            switch (type) {
            case OFPPMPT14_ETHERNET:
                error = parse_port_mod_ethernet_property(&property, pm);
                break;

            default:
                error = OFPPROP_UNKNOWN(loose, "port_mod", type);
                break;
            }

            if (error) {
                return error;
            }
        }
    } else {
        return OFPERR_OFPBRC_BAD_TYPE;
    }

    pm->config &= pm->mask;
    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_port_stats_request(const struct ofp_header *request,
                                  ofp_port_t *ofp10_port)
{
    switch ((enum ofp_version)request->version) {
    case OFP16_VERSION:
    case OFP15_VERSION:
    case OFP14_VERSION:
    case OFP13_VERSION:
    case OFP12_VERSION:
    case OFP11_VERSION: {
        const struct ofp11_port_stats_request *psr11 = ofpmsg_body(request);
        return ofputil_port_from_ofp11(psr11->port_no, ofp10_port);
    }

    case OFP10_VERSION: {
        const struct ofp10_port_stats_request *psr10 = ofpmsg_body(request);
        *ofp10_port = u16_to_ofp(ntohs(psr10->port_no));
        return 0;
    }

    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_decode_port_status(const struct ofp_header *oh,
                           struct ofputil_port_status *ps)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    ofpraw_pull_assert(&b);

    const struct ofp_port_status *ops = ofpbuf_pull(&b, sizeof *ops);
    if (ops->reason != OFPPR_ADD &&
        ops->reason != OFPPR_DELETE &&
        ops->reason != OFPPR_MODIFY) {
        return OFPERR_NXBRC_BAD_REASON;
    }
    ps->reason = ops->reason;

    int retval = ofputil_pull_phy_port(oh->version, &b, &ps->desc);
    ovs_assert(retval != EOF);
    return retval;
}

Project: ovs
File: ofp-util.c

ofputil_decode_queue_get_config_request(const struct ofp_header *oh,
                                        ofp_port_t *port, uint32_t *queue)
{
    const struct ofp10_queue_get_config_request *qgcr10;
    const struct ofp11_queue_get_config_request *qgcr11;
    const struct ofp14_queue_desc_request *qdr14;
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);

    switch ((int) raw) {
    case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST:
        qgcr10 = b.data;
        *port = u16_to_ofp(ntohs(qgcr10->port));
        *queue = OFPQ_ALL;
        break;

    case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST:
        qgcr11 = b.data;
        *queue = OFPQ_ALL;
        enum ofperr error = ofputil_port_from_ofp11(qgcr11->port, port);
        if (error || *port == OFPP_ANY) {
            return error;
        }
        break;

    case OFPRAW_OFPST14_QUEUE_DESC_REQUEST:
        qdr14 = b.data;
        *queue = ntohl(qdr14->queue);
        return ofputil_port_from_ofp11(qdr14->port, port);

    default:
        OVS_NOT_REACHED();
    }

    return (ofp_to_u16(*port) < ofp_to_u16(OFPP_MAX)
            ? 0
            : OFPERR_OFPQOFC_BAD_PORT);
}

Project: ovs
File: ofp-util.c

ofputil_decode_queue_stats(struct ofputil_queue_stats *qs, struct ofpbuf *msg)
{
    enum ofperr error;
    enum ofpraw raw;

    error = (msg->header ? ofpraw_decode(&raw, msg->header)
             : ofpraw_pull(&raw, msg));
    if (error) {
        return error;
    }

    if (!msg->size) {
        return EOF;
    } else if (raw == OFPRAW_OFPST14_QUEUE_REPLY) {
        return ofputil_pull_ofp14_queue_stats(qs, msg);
    } else if (raw == OFPRAW_OFPST13_QUEUE_REPLY) {
        const struct ofp13_queue_stats *qs13;

        qs13 = ofpbuf_try_pull(msg, sizeof *qs13);
        if (!qs13) {
            goto bad_len;
        }
        return ofputil_queue_stats_from_ofp13(qs, qs13);
    } else if (raw == OFPRAW_OFPST11_QUEUE_REPLY) {
        const struct ofp11_queue_stats *qs11;

        qs11 = ofpbuf_try_pull(msg, sizeof *qs11);
        if (!qs11) {
            goto bad_len;
        }
        return ofputil_queue_stats_from_ofp11(qs, qs11);
    } else if (raw == OFPRAW_OFPST10_QUEUE_REPLY) {
        const struct ofp10_queue_stats *qs10;

        qs10 = ofpbuf_try_pull(msg, sizeof *qs10);
        if (!qs10) {
            goto bad_len;
        }
        return ofputil_queue_stats_from_ofp10(qs, qs10);
    } else {
        OVS_NOT_REACHED();
    }

 bad_len:
    VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %"PRIu32" leftover "
                 "bytes at end", msg->size);
    return OFPERR_OFPBRC_BAD_LEN;
}

Project: ovs
File: ofp-util.c

ofputil_decode_queue_stats_request(const struct ofp_header *request,
                                   struct ofputil_queue_stats_request *oqsr)
{
    switch ((enum ofp_version)request->version) {
    case OFP16_VERSION:
    case OFP15_VERSION:
    case OFP14_VERSION:
    case OFP13_VERSION:
    case OFP12_VERSION:
    case OFP11_VERSION: {
        const struct ofp11_queue_stats_request *qsr11 = ofpmsg_body(request);
        oqsr->queue_id = ntohl(qsr11->queue_id);
        return ofputil_port_from_ofp11(qsr11->port_no, &oqsr->port_no);
    }

    case OFP10_VERSION: {
        const struct ofp10_queue_stats_request *qsr10 = ofpmsg_body(request);
        oqsr->queue_id = ntohl(qsr10->queue_id);
        oqsr->port_no = u16_to_ofp(ntohs(qsr10->port_no));
        /* OF 1.0 uses OFPP_ALL for OFPP_ANY */
        if (oqsr->port_no == OFPP_ALL) {
            oqsr->port_no = OFPP_ANY;
        }
        return 0;
    }

    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_decode_requestforward(const struct ofp_header *outer,
                              struct ofputil_requestforward *rf)
{
    struct ofpbuf b = ofpbuf_const_initializer(outer, ntohs(outer->length));

    /* Skip past outer message. */
    enum ofpraw outer_raw = ofpraw_pull_assert(&b);
    ovs_assert(outer_raw == OFPRAW_OFPT14_REQUESTFORWARD);

    /* Validate inner message. */
    if (b.size < sizeof(struct ofp_header)) {
        return OFPERR_OFPBFC_MSG_BAD_LEN;
    }
    const struct ofp_header *inner = b.data;
    unsigned int inner_len = ntohs(inner->length);
    if (inner_len < sizeof(struct ofp_header) || inner_len > b.size) {
        return OFPERR_OFPBFC_MSG_BAD_LEN;
    }
    if (inner->version != outer->version) {
        return OFPERR_OFPBRC_BAD_VERSION;
    }

    /* Parse inner message. */
    enum ofptype type;
    enum ofperr error = ofptype_decode(&type, inner);
    if (error) {
        return error;
    }

    rf->xid = inner->xid;
    if (type == OFPTYPE_GROUP_MOD) {
        rf->reason = OFPRFR_GROUP_MOD;
        rf->group_mod = xmalloc(sizeof *rf->group_mod);
        error = ofputil_decode_group_mod(inner, rf->group_mod);
        if (error) {
            free(rf->group_mod);
            return error;
        }
    } else if (type == OFPTYPE_METER_MOD) {
        rf->reason = OFPRFR_METER_MOD;
        rf->meter_mod = xmalloc(sizeof *rf->meter_mod);
        ofpbuf_init(&rf->bands, 64);
        error = ofputil_decode_meter_mod(inner, rf->meter_mod, &rf->bands);
        if (error) {
            free(rf->meter_mod);
            ofpbuf_uninit(&rf->bands);
            return error;
        }
    } else {
        return OFPERR_OFPBFC_MSG_UNSUP;
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_role_message(const struct ofp_header *oh,
                            struct ofputil_role_request *rr)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);
    if (raw == OFPRAW_OFPT12_ROLE_REQUEST ||
        raw == OFPRAW_OFPT12_ROLE_REPLY) {
        const struct ofp12_role_request *orr = b.msg;

        if (orr->role != htonl(OFPCR12_ROLE_NOCHANGE) &&
            orr->role != htonl(OFPCR12_ROLE_EQUAL) &&
            orr->role != htonl(OFPCR12_ROLE_MASTER) &&
            orr->role != htonl(OFPCR12_ROLE_SLAVE)) {
            return OFPERR_OFPRRFC_BAD_ROLE;
        }

        rr->role = ntohl(orr->role);
        if (raw == OFPRAW_OFPT12_ROLE_REQUEST
            ? orr->role == htonl(OFPCR12_ROLE_NOCHANGE)
            : orr->generation_id == OVS_BE64_MAX) {
            rr->have_generation_id = false;
            rr->generation_id = 0;
        } else {
            rr->have_generation_id = true;
            rr->generation_id = ntohll(orr->generation_id);
        }
    } else if (raw == OFPRAW_NXT_ROLE_REQUEST ||
               raw == OFPRAW_NXT_ROLE_REPLY) {
        const struct nx_role_request *nrr = b.msg;

        BUILD_ASSERT(NX_ROLE_OTHER + 1 == OFPCR12_ROLE_EQUAL);
        BUILD_ASSERT(NX_ROLE_MASTER + 1 == OFPCR12_ROLE_MASTER);
        BUILD_ASSERT(NX_ROLE_SLAVE + 1 == OFPCR12_ROLE_SLAVE);

        if (nrr->role != htonl(NX_ROLE_OTHER) &&
            nrr->role != htonl(NX_ROLE_MASTER) &&
            nrr->role != htonl(NX_ROLE_SLAVE)) {
            return OFPERR_OFPRRFC_BAD_ROLE;
        }

        rr->role = ntohl(nrr->role) + 1;
        rr->have_generation_id = false;
        rr->generation_id = 0;
    } else {
        OVS_NOT_REACHED();
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_role_status(const struct ofp_header *oh,
                           struct ofputil_role_status *rs)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);
    ovs_assert(raw == OFPRAW_OFPT14_ROLE_STATUS);

    const struct ofp14_role_status *r = b.msg;
    if (r->role != htonl(OFPCR12_ROLE_NOCHANGE) &&
        r->role != htonl(OFPCR12_ROLE_EQUAL) &&
        r->role != htonl(OFPCR12_ROLE_MASTER) &&
        r->role != htonl(OFPCR12_ROLE_SLAVE)) {
        return OFPERR_OFPRRFC_BAD_ROLE;
    }

    rs->role = ntohl(r->role);
    rs->generation_id = ntohll(r->generation_id);
    rs->reason = r->reason;

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_set_async_config(const struct ofp_header *oh, bool loose,
                                const struct ofputil_async_cfg *basis,
                                struct ofputil_async_cfg *ac)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);

    if (raw == OFPRAW_OFPT13_SET_ASYNC ||
        raw == OFPRAW_NXT_SET_ASYNC_CONFIG ||
        raw == OFPRAW_OFPT13_GET_ASYNC_REPLY) {
        const struct nx_async_config *msg = ofpmsg_body(oh);

        *ac = OFPUTIL_ASYNC_CFG_INIT;
        decode_legacy_async_masks(msg->packet_in_mask, OAM_PACKET_IN,
                                  oh->version, ac);
        decode_legacy_async_masks(msg->port_status_mask, OAM_PORT_STATUS,
                                  oh->version, ac);
        decode_legacy_async_masks(msg->flow_removed_mask, OAM_FLOW_REMOVED,
                                  oh->version, ac);
    } else if (raw == OFPRAW_OFPT14_SET_ASYNC ||
               raw == OFPRAW_OFPT14_GET_ASYNC_REPLY ||
               raw == OFPRAW_NXT_SET_ASYNC_CONFIG2) {
        *ac = *basis;
        while (b.size > 0) {
            struct ofpbuf property;
            enum ofperr error;
            uint64_t type;

            error = ofpprop_pull__(&b, &property, 8, 0xfffe, &type);
            if (error) {
                return error;
            }

            const struct ofp14_async_prop *ap
                = get_ofp14_async_config_prop_by_prop_type(type);
            error = (ap
                     ? parse_async_tlv(&property, ap, ac, oh->version, loose)
                     : OFPPROP_UNKNOWN(loose, "async config", type));
            if (error) {
                /* Most messages use OFPBPC_BAD_TYPE but async has its own (who
                 * knows why, it's OpenFlow. */
                if (error == OFPERR_OFPBPC_BAD_TYPE) {
                    error = OFPERR_OFPACFC_UNSUPPORTED;
                }
                return error;
            }
        }
    } else {
        return OFPERR_OFPBRC_BAD_VERSION;
    }
    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_set_config(const struct ofp_header *oh,
                          struct ofputil_switch_config *config)
{
    return (ofputil_decode_switch_config(oh, config)
            ? 0
            : OFPERR_OFPSCFC_BAD_FLAGS);
}

Project: ovs
File: ofp-util.c

ofputil_decode_switch_config(const struct ofp_header *oh,
                             struct ofputil_switch_config *config)
{
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    ofpraw_pull_assert(&b);

    const struct ofp_switch_config *osc = ofpbuf_pull(&b, sizeof *osc);
    config->frag = ntohs(osc->flags) & OFPC_FRAG_MASK;
    config->miss_send_len = ntohs(osc->miss_send_len);

    ovs_be16 valid_mask = htons(OFPC_FRAG_MASK);
    if (oh->version < OFP13_VERSION) {
        const ovs_be16 ttl_bit = htons(OFPC_INVALID_TTL_TO_CONTROLLER);
        valid_mask |= ttl_bit;
        config->invalid_ttl_to_controller = (osc->flags & ttl_bit) != 0;
    } else {
        config->invalid_ttl_to_controller = -1;
    }

    return !(osc->flags & ~valid_mask);
}

Project: ovs
File: ofp-util.c

ofputil_decode_table_desc(struct ofpbuf *msg,
                          struct ofputil_table_desc *td,
                          enum ofp_version version)
{
    memset(td, 0, sizeof *td);

    if (!msg->header) {
        ofpraw_pull_assert(msg);
    }

    if (!msg->size) {
        return EOF;
    }

    struct ofp14_table_desc *otd = ofpbuf_try_pull(msg, sizeof *otd);
    if (!otd) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "OFP14_TABLE_DESC reply has %"PRIu32" "
                     "leftover bytes at end", msg->size);
        return OFPERR_OFPBRC_BAD_LEN;
    }

    td->table_id = otd->table_id;
    size_t length = ntohs(otd->length);
    if (length < sizeof *otd || length - sizeof *otd > msg->size) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "OFP14_TABLE_DESC reply claims invalid "
                     "length %"PRIuSIZE, length);
        return OFPERR_OFPBRC_BAD_LEN;
    }
    length -= sizeof *otd;

    td->eviction = ofputil_decode_table_eviction(otd->config, version);
    td->vacancy = ofputil_decode_table_vacancy(otd->config, version);
    td->eviction_flags = UINT32_MAX;

    struct ofpbuf properties = ofpbuf_const_initializer(
        ofpbuf_pull(msg, length), length);
    while (properties.size > 0) {
        struct ofpbuf payload;
        enum ofperr error;
        uint64_t type;

        error = ofpprop_pull(&properties, &payload, &type);
        if (error) {
            return error;
        }

        switch (type) {
        case OFPTMPT14_EVICTION:
            error = ofpprop_parse_u32(&payload, &td->eviction_flags);
            break;

        case OFPTMPT14_VACANCY:
            error = parse_table_desc_vacancy_property(&payload, td);
            break;

        default:
            error = OFPPROP_UNKNOWN(true, "table_desc", type);
            break;
        }

        if (error) {
            return error;
        }
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_table_eviction(ovs_be32 config, enum ofp_version version)
{
    return (version < OFP14_VERSION ? OFPUTIL_TABLE_EVICTION_DEFAULT
            : config & htonl(OFPTC14_EVICTION) ? OFPUTIL_TABLE_EVICTION_ON
            : OFPUTIL_TABLE_EVICTION_OFF);
}

Project: ovs
File: ofp-util.c

ofputil_decode_table_features(struct ofpbuf *msg,
                              struct ofputil_table_features *tf, bool loose)
{
    memset(tf, 0, sizeof *tf);

    if (!msg->header) {
        ofpraw_pull_assert(msg);
    }

    if (!msg->size) {
        return EOF;
    }

    const struct ofp_header *oh = msg->header;
    struct ofp13_table_features *otf = msg->data;
    if (msg->size < sizeof *otf) {
        return OFPERR_OFPBPC_BAD_LEN;
    }

    unsigned int len = ntohs(otf->length);
    if (len < sizeof *otf || len % 8 || len > msg->size) {
        return OFPERR_OFPBPC_BAD_LEN;
    }

    tf->table_id = otf->table_id;
    if (tf->table_id == OFPTT_ALL) {
        return OFPERR_OFPTFFC_BAD_TABLE;
    }

    ovs_strlcpy(tf->name, otf->name, OFP_MAX_TABLE_NAME_LEN);
    tf->metadata_match = otf->metadata_match;
    tf->metadata_write = otf->metadata_write;
    tf->miss_config = OFPUTIL_TABLE_MISS_DEFAULT;
    if (oh->version >= OFP14_VERSION) {
        uint32_t caps = ntohl(otf->capabilities);
        tf->supports_eviction = (caps & OFPTC14_EVICTION) != 0;
        tf->supports_vacancy_events = (caps & OFPTC14_VACANCY_EVENTS) != 0;
    } else {
        tf->supports_eviction = -1;
        tf->supports_vacancy_events = -1;
    }
    tf->max_entries = ntohl(otf->max_entries);

    struct ofpbuf properties = ofpbuf_const_initializer(ofpbuf_pull(msg, len),
                                                        len);
    ofpbuf_pull(&properties, sizeof *otf);
    while (properties.size > 0) {
        struct ofpbuf payload;
        enum ofperr error;
        uint64_t type;

        error = pull_table_feature_property(&properties, &payload, &type);
        if (error) {
            return error;
        }

        switch ((enum ofp13_table_feature_prop_type) type) {
        case OFPTFPT13_INSTRUCTIONS:
            error = parse_instruction_ids(&payload, loose,
                                          &tf->nonmiss.instructions);
            break;
        case OFPTFPT13_INSTRUCTIONS_MISS:
            error = parse_instruction_ids(&payload, loose,
                                          &tf->miss.instructions);
            break;

        case OFPTFPT13_NEXT_TABLES:
            error = parse_table_features_next_table(&payload,
                                                    tf->nonmiss.next);
            break;
        case OFPTFPT13_NEXT_TABLES_MISS:
            error = parse_table_features_next_table(&payload, tf->miss.next);
            break;

        case OFPTFPT13_WRITE_ACTIONS:
            error = parse_action_bitmap(&payload, oh->version,
                                        &tf->nonmiss.write.ofpacts);
            break;
        case OFPTFPT13_WRITE_ACTIONS_MISS:
            error = parse_action_bitmap(&payload, oh->version,
                                        &tf->miss.write.ofpacts);
            break;

        case OFPTFPT13_APPLY_ACTIONS:
            error = parse_action_bitmap(&payload, oh->version,
                                        &tf->nonmiss.apply.ofpacts);
            break;
        case OFPTFPT13_APPLY_ACTIONS_MISS:
            error = parse_action_bitmap(&payload, oh->version,
                                        &tf->miss.apply.ofpacts);
            break;

        case OFPTFPT13_MATCH:
            error = parse_oxms(&payload, loose, &tf->match, &tf->mask);
            break;
        case OFPTFPT13_WILDCARDS:
            error = parse_oxms(&payload, loose, &tf->wildcard, NULL);
            break;

        case OFPTFPT13_WRITE_SETFIELD:
            error = parse_oxms(&payload, loose,
                               &tf->nonmiss.write.set_fields, NULL);
            break;
        case OFPTFPT13_WRITE_SETFIELD_MISS:
            error = parse_oxms(&payload, loose,
                               &tf->miss.write.set_fields, NULL);
            break;
        case OFPTFPT13_APPLY_SETFIELD:
            error = parse_oxms(&payload, loose,
                               &tf->nonmiss.apply.set_fields, NULL);
            break;
        case OFPTFPT13_APPLY_SETFIELD_MISS:
            error = parse_oxms(&payload, loose,
                               &tf->miss.apply.set_fields, NULL);
            break;

        case OFPTFPT13_EXPERIMENTER:
        case OFPTFPT13_EXPERIMENTER_MISS:
        default:
            error = OFPPROP_UNKNOWN(loose, "table features", type);
            break;
        }
        if (error) {
            return error;
        }
    }

    /* Fix inconsistencies:
     *
     *     - Turn on 'match' bits that are set in 'mask', because maskable
     *       fields are matchable.
     *
     *     - Turn on 'wildcard' bits that are set in 'mask', because a field
     *       that is arbitrarily maskable can be wildcarded entirely.
     *
     *     - Turn off 'wildcard' bits that are not in 'match', because a field
     *       must be matchable for it to be meaningfully wildcarded. */
    bitmap_or(tf->match.bm, tf->mask.bm, MFF_N_IDS);
    bitmap_or(tf->wildcard.bm, tf->mask.bm, MFF_N_IDS);
    bitmap_and(tf->wildcard.bm, tf->match.bm, MFF_N_IDS);

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_table_miss(ovs_be32 config_, enum ofp_version version)
{
    uint32_t config = ntohl(config_);

    if (version == OFP11_VERSION || version == OFP12_VERSION) {
        switch (config & OFPTC11_TABLE_MISS_MASK) {
        case OFPTC11_TABLE_MISS_CONTROLLER:
            return OFPUTIL_TABLE_MISS_CONTROLLER;

        case OFPTC11_TABLE_MISS_CONTINUE:
            return OFPUTIL_TABLE_MISS_CONTINUE;

        case OFPTC11_TABLE_MISS_DROP:
            return OFPUTIL_TABLE_MISS_DROP;

        default:
            VLOG_WARN_RL(&bad_ofmsg_rl, "bad table miss config %d", config);
            return OFPUTIL_TABLE_MISS_CONTROLLER;
        }
    } else {
        return OFPUTIL_TABLE_MISS_DEFAULT;
    }
}

Project: ovs
File: ofp-util.c

ofputil_decode_table_mod(const struct ofp_header *oh,
                         struct ofputil_table_mod *pm)
{
    memset(pm, 0, sizeof *pm);
    pm->miss = OFPUTIL_TABLE_MISS_DEFAULT;
    pm->eviction = OFPUTIL_TABLE_EVICTION_DEFAULT;
    pm->eviction_flags = UINT32_MAX;
    pm->vacancy = OFPUTIL_TABLE_VACANCY_DEFAULT;

    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
    enum ofpraw raw = ofpraw_pull_assert(&b);
    if (raw == OFPRAW_OFPT11_TABLE_MOD) {
        const struct ofp11_table_mod *otm = b.data;

        pm->table_id = otm->table_id;
        pm->miss = ofputil_decode_table_miss(otm->config, oh->version);
    } else if (raw == OFPRAW_OFPT14_TABLE_MOD) {
        const struct ofp14_table_mod *otm = ofpbuf_pull(&b, sizeof *otm);

        pm->table_id = otm->table_id;
        pm->miss = ofputil_decode_table_miss(otm->config, oh->version);
        pm->eviction = ofputil_decode_table_eviction(otm->config, oh->version);
        pm->vacancy = ofputil_decode_table_vacancy(otm->config, oh->version);
        while (b.size > 0) {
            struct ofpbuf property;
            enum ofperr error;
            uint64_t type;

            error = ofpprop_pull(&b, &property, &type);
            if (error) {
                return error;
            }

            switch (type) {
            case OFPTMPT14_EVICTION:
                error = ofpprop_parse_u32(&property, &pm->eviction);
                break;

            case OFPTMPT14_VACANCY:
                error = parse_table_mod_vacancy_property(&property, pm);
                break;

            default:
                error = OFPERR_OFPBRC_BAD_TYPE;
                break;
            }

            if (error) {
                return error;
            }
        }
    } else {
        return OFPERR_OFPBRC_BAD_TYPE;
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_table_status(const struct ofp_header *oh,
                            struct ofputil_table_status *ts)
{
    const struct ofp14_table_status *ots;
    struct ofpbuf b;
    enum ofperr error;
    enum ofpraw raw;

    ofpbuf_use_const(&b, oh, ntohs(oh->length));
    raw = ofpraw_pull_assert(&b);
    ots = ofpbuf_pull(&b, sizeof *ots);

    if (raw == OFPRAW_OFPT14_TABLE_STATUS) {
        if (ots->reason != OFPTR_VACANCY_DOWN
            && ots->reason != OFPTR_VACANCY_UP) {
            return OFPERR_OFPBPC_BAD_VALUE;
        }
        ts->reason = ots->reason;

        error = ofputil_decode_table_desc(&b, &ts->desc, oh->version);
        return error;
    } else {
        return OFPERR_OFPBRC_BAD_VERSION;
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_decode_table_vacancy(ovs_be32 config, enum ofp_version version)
{
    return (version < OFP14_VERSION ? OFPUTIL_TABLE_VACANCY_DEFAULT
            : config & htonl(OFPTC14_VACANCY_EVENTS) ? OFPUTIL_TABLE_VACANCY_ON
            : OFPUTIL_TABLE_VACANCY_OFF);
}

Project: ovs
File: ofp-util.c

ofputil_decode_tlv_table_mod(const struct ofp_header *oh,
                                struct ofputil_tlv_table_mod *ttm)
{
    struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
    ofpraw_pull_assert(&msg);

    struct nx_tlv_table_mod *nx_ttm = ofpbuf_pull(&msg, sizeof *nx_ttm);
    ttm->command = ntohs(nx_ttm->command);
    if (ttm->command > NXTTMC_CLEAR) {
        VLOG_WARN_RL(&bad_ofmsg_rl,
                     "tlv table mod command (%u) is out of range",
                     ttm->command);
        return OFPERR_NXTTMFC_BAD_COMMAND;
    }

    return decode_tlv_table_mappings(&msg, TUN_METADATA_NUM_OPTS,
                                        &ttm->mappings);
}

Project: ovs
File: ofp-util.c

ofputil_decode_tlv_table_reply(const struct ofp_header *oh,
                                  struct ofputil_tlv_table_reply *ttr)
{
    struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
    ofpraw_pull_assert(&msg);

    struct nx_tlv_table_reply *nx_ttr = ofpbuf_pull(&msg, sizeof *nx_ttr);
    ttr->max_option_space = ntohl(nx_ttr->max_option_space);
    ttr->max_fields = ntohs(nx_ttr->max_fields);

    return decode_tlv_table_mappings(&msg, ttr->max_fields, &ttr->mappings);
}

Project: ovs
File: ofp-util.c

ofputil_destroy_requestforward(struct ofputil_requestforward *rf)
{
    if (!rf) {
        return;
    }

    switch (rf->reason) {
    case OFPRFR_GROUP_MOD:
        ofputil_uninit_group_mod(rf->group_mod);
        free(rf->group_mod);
        break;

    case OFPRFR_METER_MOD:
        ofpbuf_uninit(&rf->bands);
        free(rf->meter_mod);
        break;

    case OFPRFR_N_REASONS:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_dl_type_from_openflow(ovs_be16 ofp_dl_type)
{
    return (ofp_dl_type == htons(OFP_DL_TYPE_NOT_ETH_TYPE)
            ? htons(FLOW_DL_TYPE_NONE)
            : ofp_dl_type);
}

Project: ovs
File: ofp-util.c

ofputil_encode_aggregate_stats_reply(
    const struct ofputil_aggregate_stats *stats,
    const struct ofp_header *request)
{
    struct ofp_aggregate_stats_reply *asr;
    uint64_t packet_count;
    uint64_t byte_count;
    struct ofpbuf *msg;
    enum ofpraw raw;

    ofpraw_decode(&raw, request);
    if (raw == OFPRAW_OFPST10_AGGREGATE_REQUEST) {
        packet_count = unknown_to_zero(stats->packet_count);
        byte_count = unknown_to_zero(stats->byte_count);
    } else {
        packet_count = stats->packet_count;
        byte_count = stats->byte_count;
    }

    msg = ofpraw_alloc_stats_reply(request, 0);
    asr = ofpbuf_put_zeros(msg, sizeof *asr);
    put_32aligned_be64(&asr->packet_count, htonll(packet_count));
    put_32aligned_be64(&asr->byte_count, htonll(byte_count));
    asr->flow_count = htonl(stats->flow_count);

    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_barrier_request(enum ofp_version ofp_version)
{
    enum ofpraw type;

    switch (ofp_version) {
    case OFP16_VERSION:
    case OFP15_VERSION:
    case OFP14_VERSION:
    case OFP13_VERSION:
    case OFP12_VERSION:
    case OFP11_VERSION:
        type = OFPRAW_OFPT11_BARRIER_REQUEST;
        break;

    case OFP10_VERSION:
        type = OFPRAW_OFPT10_BARRIER_REQUEST;
        break;

    default:
        OVS_NOT_REACHED();
    }

    return ofpraw_alloc(type, ofp_version, 0);
}

Project: ovs
File: ofp-util.c

ofputil_encode_bundle_add(enum ofp_version ofp_version,
                          struct ofputil_bundle_add_msg *msg)
{
    struct ofpbuf *request;
    struct ofp14_bundle_ctrl_msg *m;

    /* Must use the same xid as the embedded message. */
    request = ofpraw_alloc_xid(ofp_version == OFP13_VERSION
                               ? OFPRAW_ONFT13_BUNDLE_ADD_MESSAGE
                               : OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE, ofp_version,
                               msg->msg->xid, ntohs(msg->msg->length));
    m = ofpbuf_put_zeros(request, sizeof *m);

    m->bundle_id = htonl(msg->bundle_id);
    m->flags = htons(msg->flags);
    ofpbuf_put(request, msg->msg, ntohs(msg->msg->length));

    ofpmsg_update_length(request);
    return request;
}

Project: ovs
File: ofp-util.c

ofputil_encode_bundle_ctrl_reply(const struct ofp_header *oh,
                                 struct ofputil_bundle_ctrl_msg *msg)
{
    struct ofpbuf *buf;
    struct ofp14_bundle_ctrl_msg *m;

    buf = ofpraw_alloc_reply(oh->version == OFP13_VERSION
                             ? OFPRAW_ONFT13_BUNDLE_CONTROL
                             : OFPRAW_OFPT14_BUNDLE_CONTROL, oh, 0);
    m = ofpbuf_put_zeros(buf, sizeof *m);

    m->bundle_id = htonl(msg->bundle_id);
    m->type = htons(msg->type);
    m->flags = htons(msg->flags);

    return buf;
}

Project: ovs
File: ofp-util.c

ofputil_encode_bundle_ctrl_request(enum ofp_version ofp_version,
                                   struct ofputil_bundle_ctrl_msg *bc)
{
    struct ofpbuf *request;
    struct ofp14_bundle_ctrl_msg *m;

    switch (ofp_version) {
    case OFP10_VERSION:
    case OFP11_VERSION:
    case OFP12_VERSION:
        ovs_fatal(0, "bundles need OpenFlow 1.3 or later "
                     "(\'-O OpenFlow14\')");
    case OFP13_VERSION:
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION:
        request = ofpraw_alloc(ofp_version == OFP13_VERSION
                               ? OFPRAW_ONFT13_BUNDLE_CONTROL
                               : OFPRAW_OFPT14_BUNDLE_CONTROL, ofp_version, 0);
        m = ofpbuf_put_zeros(request, sizeof *m);

        m->bundle_id = htonl(bc->bundle_id);
        m->type = htons(bc->type);
        m->flags = htons(bc->flags);
        break;
    default:
        OVS_NOT_REACHED();
    }

    return request;
}

Project: ovs
File: ofp-util.c

ofputil_encode_bundle_msgs(const struct ofputil_bundle_msg *bms,
                           size_t n_bms, struct ovs_list *requests,
                           enum ofputil_protocol protocol)
{
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);

    for (size_t i = 0; i < n_bms; i++) {
        struct ofpbuf *request = NULL;

        switch ((int)bms[i].type) {
        case OFPTYPE_FLOW_MOD:
            request = ofputil_encode_flow_mod(&bms[i].fm, protocol);
            break;
        case OFPTYPE_GROUP_MOD:
            request = ofputil_encode_group_mod(version, &bms[i].gm);
            break;
        case OFPTYPE_PACKET_OUT:
            request = ofputil_encode_packet_out(&bms[i].po, protocol);
            break;
        default:
            break;
        }
        if (request) {
            ovs_list_push_back(requests, &request->list_node);
        }
    }
}

Project: ovs
File: ofp-util.c

ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
                        enum ofputil_protocol protocol)
{
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
    ovs_be16 raw_flags = ofputil_encode_flow_mod_flags(fm->flags, version);
    struct ofpbuf *msg;

    switch (protocol) {
    case OFPUTIL_P_OF11_STD:
    case OFPUTIL_P_OF12_OXM:
    case OFPUTIL_P_OF13_OXM:
    case OFPUTIL_P_OF14_OXM:
    case OFPUTIL_P_OF15_OXM:
    case OFPUTIL_P_OF16_OXM: {
        struct ofp11_flow_mod *ofm;
        int tailroom;

        tailroom = ofputil_match_typical_len(protocol) + fm->ofpacts_len;
        msg = ofpraw_alloc(OFPRAW_OFPT11_FLOW_MOD, version, tailroom);
        ofm = ofpbuf_put_zeros(msg, sizeof *ofm);
        if ((protocol == OFPUTIL_P_OF11_STD
             && (fm->command == OFPFC_MODIFY ||
                 fm->command == OFPFC_MODIFY_STRICT)
             && fm->cookie_mask == htonll(0))
            || fm->command == OFPFC_ADD) {
            ofm->cookie = fm->new_cookie;
        } else {
            ofm->cookie = fm->cookie & fm->cookie_mask;
        }
        ofm->cookie_mask = fm->cookie_mask;
        if (fm->table_id != OFPTT_ALL
            || (protocol != OFPUTIL_P_OF11_STD
                && (fm->command == OFPFC_DELETE ||
                    fm->command == OFPFC_DELETE_STRICT))) {
            ofm->table_id = fm->table_id;
        } else {
            ofm->table_id = 0;
        }
        ofm->command = fm->command;
        ofm->idle_timeout = htons(fm->idle_timeout);
        ofm->hard_timeout = htons(fm->hard_timeout);
        ofm->priority = htons(fm->priority);
        ofm->buffer_id = htonl(fm->buffer_id);
        ofm->out_port = ofputil_port_to_ofp11(fm->out_port);
        ofm->out_group = htonl(fm->out_group);
        ofm->flags = raw_flags;
        if (version >= OFP14_VERSION && fm->command == OFPFC_ADD) {
            ofm->importance = htons(fm->importance);
        } else {
            ofm->importance = 0;
        }
        ofputil_put_ofp11_match(msg, &fm->match, protocol);
        ofpacts_put_openflow_instructions(fm->ofpacts, fm->ofpacts_len, msg,
                                          version);
        break;
    }

    case OFPUTIL_P_OF10_STD:
    case OFPUTIL_P_OF10_STD_TID: {
        struct ofp10_flow_mod *ofm;

        msg = ofpraw_alloc(OFPRAW_OFPT10_FLOW_MOD, OFP10_VERSION,
                           fm->ofpacts_len);
        ofm = ofpbuf_put_zeros(msg, sizeof *ofm);
        ofputil_match_to_ofp10_match(&fm->match, &ofm->match);
        ofm->cookie = fm->new_cookie;
        ofm->command = ofputil_tid_command(fm, protocol);
        ofm->idle_timeout = htons(fm->idle_timeout);
        ofm->hard_timeout = htons(fm->hard_timeout);
        ofm->priority = htons(fm->priority);
        ofm->buffer_id = htonl(fm->buffer_id);
        ofm->out_port = htons(ofp_to_u16(fm->out_port));
        ofm->flags = raw_flags;
        ofpacts_put_openflow_actions(fm->ofpacts, fm->ofpacts_len, msg,
                                     version);
        break;
    }

    case OFPUTIL_P_OF10_NXM:
    case OFPUTIL_P_OF10_NXM_TID: {
        struct nx_flow_mod *nfm;
        int match_len;

        msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MOD, OFP10_VERSION,
                           NXM_TYPICAL_LEN + fm->ofpacts_len);
        nfm = ofpbuf_put_zeros(msg, sizeof *nfm);
        nfm->command = ofputil_tid_command(fm, protocol);
        nfm->cookie = fm->new_cookie;
        match_len = nx_put_match(msg, &fm->match, fm->cookie, fm->cookie_mask);
        nfm = msg->msg;
        nfm->idle_timeout = htons(fm->idle_timeout);
        nfm->hard_timeout = htons(fm->hard_timeout);
        nfm->priority = htons(fm->priority);
        nfm->buffer_id = htonl(fm->buffer_id);
        nfm->out_port = htons(ofp_to_u16(fm->out_port));
        nfm->flags = raw_flags;
        nfm->match_len = htons(match_len);
        ofpacts_put_openflow_actions(fm->ofpacts, fm->ofpacts_len, msg,
                                     version);
        break;
    }

    default:
        OVS_NOT_REACHED();
    }

    ofpmsg_update_length(msg);
    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_flow_mod_flags(enum ofputil_flow_mod_flags flags,
                              enum ofp_version version)
{
    const struct ofputil_flow_mod_flag *f;
    uint16_t raw_flags;

    raw_flags = 0;
    for (f = ofputil_flow_mod_flags; f->raw_flag; f++) {
        if (f->flag & flags
            && version >= f->min_version
            && (!f->max_version || version <= f->max_version)) {
            raw_flags |= f->raw_flag;
        }
    }

    return htons(raw_flags);
}

Project: ovs
File: ofp-util.c

ofputil_encode_flow_monitor_cancel(uint32_t id)
{
    struct nx_flow_monitor_cancel *nfmc;
    struct ofpbuf *msg;

    msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MONITOR_CANCEL, OFP10_VERSION, 0);
    nfmc = ofpbuf_put_uninit(msg, sizeof *nfmc);
    nfmc->id = htonl(id);
    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr,
                            enum ofputil_protocol protocol)
{
    struct ofpbuf *msg;
    enum ofp_flow_removed_reason reason = fr->reason;

    if (reason == OFPRR_METER_DELETE && !(protocol & OFPUTIL_P_OF14_UP)) {
        reason = OFPRR_DELETE;
    }

    switch (protocol) {
    case OFPUTIL_P_OF11_STD:
    case OFPUTIL_P_OF12_OXM:
    case OFPUTIL_P_OF13_OXM:
    case OFPUTIL_P_OF14_OXM:
    case OFPUTIL_P_OF15_OXM:
    case OFPUTIL_P_OF16_OXM: {
        struct ofp12_flow_removed *ofr;

        msg = ofpraw_alloc_xid(OFPRAW_OFPT11_FLOW_REMOVED,
                               ofputil_protocol_to_ofp_version(protocol),
                               htonl(0),
                               ofputil_match_typical_len(protocol));
        ofr = ofpbuf_put_zeros(msg, sizeof *ofr);
        ofr->cookie = fr->cookie;
        ofr->priority = htons(fr->priority);
        ofr->reason = reason;
        ofr->table_id = fr->table_id;
        ofr->duration_sec = htonl(fr->duration_sec);
        ofr->duration_nsec = htonl(fr->duration_nsec);
        ofr->idle_timeout = htons(fr->idle_timeout);
        ofr->hard_timeout = htons(fr->hard_timeout);
        ofr->packet_count = htonll(fr->packet_count);
        ofr->byte_count = htonll(fr->byte_count);
        ofputil_put_ofp11_match(msg, &fr->match, protocol);
        break;
    }

    case OFPUTIL_P_OF10_STD:
    case OFPUTIL_P_OF10_STD_TID: {
        struct ofp10_flow_removed *ofr;

        msg = ofpraw_alloc_xid(OFPRAW_OFPT10_FLOW_REMOVED, OFP10_VERSION,
                               htonl(0), 0);
        ofr = ofpbuf_put_zeros(msg, sizeof *ofr);
        ofputil_match_to_ofp10_match(&fr->match, &ofr->match);
        ofr->cookie = fr->cookie;
        ofr->priority = htons(fr->priority);
        ofr->reason = reason;
        ofr->duration_sec = htonl(fr->duration_sec);
        ofr->duration_nsec = htonl(fr->duration_nsec);
        ofr->idle_timeout = htons(fr->idle_timeout);
        ofr->packet_count = htonll(unknown_to_zero(fr->packet_count));
        ofr->byte_count = htonll(unknown_to_zero(fr->byte_count));
        break;
    }

    case OFPUTIL_P_OF10_NXM:
    case OFPUTIL_P_OF10_NXM_TID: {
        struct nx_flow_removed *nfr;
        int match_len;

        msg = ofpraw_alloc_xid(OFPRAW_NXT_FLOW_REMOVED, OFP10_VERSION,
                               htonl(0), NXM_TYPICAL_LEN);
        ofpbuf_put_zeros(msg, sizeof *nfr);
        match_len = nx_put_match(msg, &fr->match, 0, 0);

        nfr = msg->msg;
        nfr->cookie = fr->cookie;
        nfr->priority = htons(fr->priority);
        nfr->reason = reason;
        nfr->table_id = fr->table_id + 1;
        nfr->duration_sec = htonl(fr->duration_sec);
        nfr->duration_nsec = htonl(fr->duration_nsec);
        nfr->idle_timeout = htons(fr->idle_timeout);
        nfr->match_len = htons(match_len);
        nfr->packet_count = htonll(fr->packet_count);
        nfr->byte_count = htonll(fr->byte_count);
        break;
    }

    default:
        OVS_NOT_REACHED();
    }

    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr,
                                  enum ofputil_protocol protocol)
{
    struct ofpbuf *msg;
    enum ofpraw raw;

    switch (protocol) {
    case OFPUTIL_P_OF11_STD:
    case OFPUTIL_P_OF12_OXM:
    case OFPUTIL_P_OF13_OXM:
    case OFPUTIL_P_OF14_OXM:
    case OFPUTIL_P_OF15_OXM:
    case OFPUTIL_P_OF16_OXM: {
        struct ofp11_flow_stats_request *ofsr;

        raw = (fsr->aggregate
               ? OFPRAW_OFPST11_AGGREGATE_REQUEST
               : OFPRAW_OFPST11_FLOW_REQUEST);
        msg = ofpraw_alloc(raw, ofputil_protocol_to_ofp_version(protocol),
                           ofputil_match_typical_len(protocol));
        ofsr = ofpbuf_put_zeros(msg, sizeof *ofsr);
        ofsr->table_id = fsr->table_id;
        ofsr->out_port = ofputil_port_to_ofp11(fsr->out_port);
        ofsr->out_group = htonl(fsr->out_group);
        ofsr->cookie = fsr->cookie;
        ofsr->cookie_mask = fsr->cookie_mask;
        ofputil_put_ofp11_match(msg, &fsr->match, protocol);
        break;
    }

    case OFPUTIL_P_OF10_STD:
    case OFPUTIL_P_OF10_STD_TID: {
        struct ofp10_flow_stats_request *ofsr;

        raw = (fsr->aggregate
               ? OFPRAW_OFPST10_AGGREGATE_REQUEST
               : OFPRAW_OFPST10_FLOW_REQUEST);
        msg = ofpraw_alloc(raw, OFP10_VERSION, 0);
        ofsr = ofpbuf_put_zeros(msg, sizeof *ofsr);
        ofputil_match_to_ofp10_match(&fsr->match, &ofsr->match);
        ofsr->table_id = fsr->table_id;
        ofsr->out_port = htons(ofp_to_u16(fsr->out_port));
        break;
    }

    case OFPUTIL_P_OF10_NXM:
    case OFPUTIL_P_OF10_NXM_TID: {
        struct nx_flow_stats_request *nfsr;
        int match_len;

        raw = (fsr->aggregate
               ? OFPRAW_NXST_AGGREGATE_REQUEST
               : OFPRAW_NXST_FLOW_REQUEST);
        msg = ofpraw_alloc(raw, OFP10_VERSION, NXM_TYPICAL_LEN);
        ofpbuf_put_zeros(msg, sizeof *nfsr);
        match_len = nx_put_match(msg, &fsr->match,
                                 fsr->cookie, fsr->cookie_mask);

        nfsr = msg->msg;
        nfsr->out_port = htons(ofp_to_u16(fsr->out_port));
        nfsr->match_len = htons(match_len);
        nfsr->table_id = fsr->table_id;
        break;
    }

    default:
        OVS_NOT_REACHED();
    }

    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_get_async_reply(const struct ofp_header *oh,
                               const struct ofputil_async_cfg *ac)
{
    struct ofpbuf *buf;

    enum ofpraw raw = (oh->version < OFP14_VERSION
                       ? OFPRAW_OFPT13_GET_ASYNC_REPLY
                       : OFPRAW_OFPT14_GET_ASYNC_REPLY);
    struct ofpbuf *reply = ofpraw_alloc_reply(raw, oh, 0);
    ofputil_put_async_config__(ac, reply,
                               raw == OFPRAW_OFPT14_GET_ASYNC_REPLY,
                               oh->version, UINT32_MAX);
    return reply;

    return buf;
}

Project: ovs
File: ofp-util.c

ofputil_encode_get_config_reply(const struct ofp_header *request,
                                const struct ofputil_switch_config *config)
{
    struct ofpbuf *b = ofpraw_alloc_reply(OFPRAW_OFPT_GET_CONFIG_REPLY,
                                          request, 0);
    return ofputil_put_switch_config(config, b);
}

Project: ovs
File: ofp-util.c

ofputil_encode_group_desc_request(enum ofp_version ofp_version,
                                  uint32_t group_id)
{
    struct ofpbuf *request;

    switch (ofp_version) {
    case OFP10_VERSION:
        ovs_fatal(0, "dump-groups needs OpenFlow 1.1 or later "
                     "(\'-O OpenFlow11\')");
    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION:
    case OFP14_VERSION:
        request = ofpraw_alloc(OFPRAW_OFPST11_GROUP_DESC_REQUEST,
                               ofp_version, 0);
        break;
    case OFP15_VERSION:
    case OFP16_VERSION: {
        struct ofp15_group_desc_request *req;
        request = ofpraw_alloc(OFPRAW_OFPST15_GROUP_DESC_REQUEST,
                               ofp_version, 0);
        req = ofpbuf_put_zeros(request, sizeof *req);
        req->group_id = htonl(group_id);
        break;
    }
    default:
        OVS_NOT_REACHED();
    }

    return request;
}

Project: ovs
File: ofp-util.c

ofputil_encode_group_features_reply(
    const struct ofputil_group_features *features,
    const struct ofp_header *request)
{
    struct ofp12_group_features_stats *ogf;
    struct ofpbuf *reply;
    int i;

    reply = ofpraw_alloc_xid(OFPRAW_OFPST12_GROUP_FEATURES_REPLY,
                             request->version, request->xid, 0);
    ogf = ofpbuf_put_zeros(reply, sizeof *ogf);
    ogf->types = htonl(features->types);
    ogf->capabilities = htonl(features->capabilities);
    for (i = 0; i < OFPGT12_N_TYPES; i++) {
        ogf->max_groups[i] = htonl(features->max_groups[i]);
        ogf->actions[i] = ofpact_bitmap_to_openflow(features->ofpacts[i],
                                                    request->version);
    }

    return reply;
}

Project: ovs
File: ofp-util.c

ofputil_encode_group_mod(enum ofp_version ofp_version,
                         const struct ofputil_group_mod *gm)
{

    switch (ofp_version) {
    case OFP10_VERSION:
        bad_group_cmd(gm->command);

    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION:
    case OFP14_VERSION:
        if (gm->command > OFPGC11_DELETE && gm->command != OFPGC11_ADD_OR_MOD) {
            bad_group_cmd(gm->command);
        }
        return ofputil_encode_ofp11_group_mod(ofp_version, gm);

    case OFP15_VERSION:
    case OFP16_VERSION:
        return ofputil_encode_ofp15_group_mod(ofp_version, gm);

    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_encode_group_stats_request(enum ofp_version ofp_version,
                                   uint32_t group_id)
{
    struct ofpbuf *request;

    switch (ofp_version) {
    case OFP10_VERSION:
        ovs_fatal(0, "dump-group-stats needs OpenFlow 1.1 or later "
                     "(\'-O OpenFlow11\')");
    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION:
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION: {
        struct ofp11_group_stats_request *req;
        request = ofpraw_alloc(OFPRAW_OFPST11_GROUP_REQUEST, ofp_version, 0);
        req = ofpbuf_put_zeros(request, sizeof *req);
        req->group_id = htonl(group_id);
        break;
    }
    default:
        OVS_NOT_REACHED();
    }

    return request;
}

Project: ovs
File: ofp-util.c

ofputil_encode_hello(uint32_t allowed_versions)
{
    enum ofp_version ofp_version;
    struct ofpbuf *msg;

    ofp_version = leftmost_1bit_idx(allowed_versions);
    msg = ofpraw_alloc(OFPRAW_OFPT_HELLO, ofp_version, 0);

    if (should_send_version_bitmap(allowed_versions)) {
        struct ofp_hello_elem_header *oheh;
        uint16_t map_len;

        map_len = sizeof allowed_versions;
        oheh = ofpbuf_put_zeros(msg, ROUND_UP(map_len + sizeof *oheh, 8));
        oheh->type = htons(OFPHET_VERSIONBITMAP);
        oheh->length = htons(map_len + sizeof *oheh);
        *ALIGNED_CAST(ovs_be32 *, oheh + 1) = htonl(allowed_versions);

        ofpmsg_update_length(msg);
    }

    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_meter_features_reply(const struct ofputil_meter_features *mf,
                                    const struct ofp_header *request)
{
    struct ofpbuf *reply;
    struct ofp13_meter_features *omf;

    reply = ofpraw_alloc_stats_reply(request, 0);
    omf = ofpbuf_put_zeros(reply, sizeof *omf);

    omf->max_meter = htonl(mf->max_meters);
    omf->band_types = htonl(mf->band_types);
    omf->capabilities = htonl(mf->capabilities);
    omf->max_bands = mf->max_bands;
    omf->max_color = mf->max_color;

    return reply;
}

Project: ovs
File: ofp-util.c

ofputil_encode_meter_mod(enum ofp_version ofp_version,
                         const struct ofputil_meter_mod *mm)
{
    struct ofpbuf *msg;

    struct ofp13_meter_mod *omm;

    msg = ofpraw_alloc(OFPRAW_OFPT13_METER_MOD, ofp_version,
                       NXM_TYPICAL_LEN + mm->meter.n_bands * 16);
    omm = ofpbuf_put_zeros(msg, sizeof *omm);
    omm->command = htons(mm->command);
    if (mm->command != OFPMC13_DELETE) {
        omm->flags = htons(mm->meter.flags);
    }
    omm->meter_id = htonl(mm->meter.meter_id);

    ofputil_put_bands(mm->meter.n_bands, mm->meter.bands, msg);

    ofpmsg_update_length(msg);
    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_meter_request(enum ofp_version ofp_version,
                             enum ofputil_meter_request_type type,
                             uint32_t meter_id)
{
    struct ofpbuf *msg;

    enum ofpraw raw;

    switch (type) {
    case OFPUTIL_METER_CONFIG:
        raw = OFPRAW_OFPST13_METER_CONFIG_REQUEST;
        break;
    case OFPUTIL_METER_STATS:
        raw = OFPRAW_OFPST13_METER_REQUEST;
        break;
    default:
    case OFPUTIL_METER_FEATURES:
        raw = OFPRAW_OFPST13_METER_FEATURES_REQUEST;
        break;
    }

    msg = ofpraw_alloc(raw, ofp_version, 0);

    if (type != OFPUTIL_METER_FEATURES) {
        struct ofp13_meter_multipart_request *omr;
        omr = ofpbuf_put_zeros(msg, sizeof *omr);
        omr->meter_id = htonl(meter_id);
    }
    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_nx_packet_in(const struct ofputil_packet_in *pin,
                            enum ofp_version version)
{
    struct nx_packet_in *npi;
    struct ofpbuf *msg;
    size_t match_len;

    /* The final argument is just an estimate of the space required. */
    msg = ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN, version,
                           htonl(0), NXM_TYPICAL_LEN + 2 + pin->packet_len);
    ofpbuf_put_zeros(msg, sizeof *npi);
    match_len = nx_put_match(msg, &pin->flow_metadata, 0, 0);
    ofpbuf_put_zeros(msg, 2);

    npi = msg->msg;
    npi->buffer_id = htonl(UINT32_MAX);
    npi->total_len = htons(pin->packet_len);
    npi->reason = encode_packet_in_reason(pin->reason, version);
    npi->table_id = pin->table_id;
    npi->cookie = pin->cookie;
    npi->match_len = htons(match_len);

    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_nx_packet_in2(const struct ofputil_packet_in_private *pin,
                             enum ofp_version version, size_t include_bytes)
{
    /* 'extra' is just an estimate of the space required. */
    size_t extra = (pin->public.packet_len
                    + NXM_TYPICAL_LEN   /* flow_metadata */
                    + pin->stack_size * 4
                    + pin->actions_len
                    + pin->action_set_len
                    + 256);     /* fudge factor */
    struct ofpbuf *msg = ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN2, version,
                                          htonl(0), extra);

    ofputil_put_packet_in_private(pin, version, include_bytes, msg);
    if (pin->public.userdata_len) {
        ofpprop_put(msg, NXPINT_USERDATA, pin->public.userdata,
                    pin->public.userdata_len);
    }

    ofpmsg_update_length(msg);
    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_nx_set_flow_format(enum nx_flow_format nxff)
{
    struct nx_set_flow_format *sff;
    struct ofpbuf *msg;

    ovs_assert(ofputil_nx_flow_format_is_valid(nxff));

    msg = ofpraw_alloc(OFPRAW_NXT_SET_FLOW_FORMAT, OFP10_VERSION, 0);
    sff = ofpbuf_put_zeros(msg, sizeof *sff);
    sff->format = htonl(nxff);

    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_ofp10_packet_in(const struct ofputil_packet_in *pin)
{
    struct ofp10_packet_in *opi;
    struct ofpbuf *msg;

    msg = ofpraw_alloc_xid(OFPRAW_OFPT10_PACKET_IN, OFP10_VERSION,
                           htonl(0), pin->packet_len);
    opi = ofpbuf_put_zeros(msg, offsetof(struct ofp10_packet_in, data));
    opi->total_len = htons(pin->packet_len);
    opi->in_port = htons(ofp_to_u16(pin->flow_metadata.flow.in_port.ofp_port));
    opi->reason = encode_packet_in_reason(pin->reason, OFP10_VERSION);
    opi->buffer_id = htonl(UINT32_MAX);

    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_ofp10_phy_port(const struct ofputil_phy_port *pp,
                              struct ofp10_phy_port *opp)
{
    memset(opp, 0, sizeof *opp);

    opp->port_no = htons(ofp_to_u16(pp->port_no));
    opp->hw_addr = pp->hw_addr;
    ovs_strlcpy(opp->name, pp->name, OFP_MAX_PORT_NAME_LEN);

    opp->config = htonl(pp->config & OFPPC10_ALL);
    opp->state = htonl(pp->state & OFPPS10_ALL);

    opp->curr = netdev_port_features_to_ofp10(pp->curr);
    opp->advertised = netdev_port_features_to_ofp10(pp->advertised);
    opp->supported = netdev_port_features_to_ofp10(pp->supported);
    opp->peer = netdev_port_features_to_ofp10(pp->peer);
}

Project: ovs
File: ofp-util.c

ofputil_encode_ofp11_group_mod(enum ofp_version ofp_version,
                               const struct ofputil_group_mod *gm)
{
    struct ofpbuf *b;
    struct ofp11_group_mod *ogm;
    size_t start_ogm;
    struct ofputil_bucket *bucket;

    b = ofpraw_alloc(OFPRAW_OFPT11_GROUP_MOD, ofp_version, 0);
    start_ogm = b->size;
    ofpbuf_put_zeros(b, sizeof *ogm);

    LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
        ofputil_put_ofp11_bucket(bucket, b, ofp_version);
    }
    ogm = ofpbuf_at_assert(b, start_ogm, sizeof *ogm);
    ogm->command = htons(gm->command);
    ogm->type = gm->type;
    ogm->group_id = htonl(gm->group_id);

    return b;
}

Project: ovs
File: ofp-util.c

ofputil_encode_ofp11_port(const struct ofputil_phy_port *pp,
                          struct ofp11_port *op)
{
    memset(op, 0, sizeof *op);

    op->port_no = ofputil_port_to_ofp11(pp->port_no);
    op->hw_addr = pp->hw_addr;
    ovs_strlcpy(op->name, pp->name, OFP_MAX_PORT_NAME_LEN);

    op->config = htonl(pp->config & OFPPC11_ALL);
    op->state = htonl(pp->state & OFPPS11_ALL);

    op->curr = netdev_port_features_to_ofp11(pp->curr);
    op->advertised = netdev_port_features_to_ofp11(pp->advertised);
    op->supported = netdev_port_features_to_ofp11(pp->supported);
    op->peer = netdev_port_features_to_ofp11(pp->peer);

    op->curr_speed = htonl(pp->curr_speed);
    op->max_speed = htonl(pp->max_speed);
}

Project: ovs
File: ofp-util.c

ofputil_encode_ofp12_packet_in(const struct ofputil_packet_in *pin,
                               enum ofp_version version)
{
    enum ofpraw raw = (version >= OFP13_VERSION
                       ? OFPRAW_OFPT13_PACKET_IN
                       : OFPRAW_OFPT12_PACKET_IN);
    struct ofpbuf *msg;

    /* The final argument is just an estimate of the space required. */
    msg = ofpraw_alloc_xid(raw, version,
                           htonl(0), NXM_TYPICAL_LEN + 2 + pin->packet_len);

    struct ofp12_packet_in *opi = ofpbuf_put_zeros(msg, sizeof *opi);
    opi->buffer_id = htonl(UINT32_MAX);
    opi->total_len = htons(pin->packet_len);
    opi->reason = encode_packet_in_reason(pin->reason, version);
    opi->table_id = pin->table_id;

    if (version >= OFP13_VERSION) {
        ovs_be64 cookie = pin->cookie;
        ofpbuf_put(msg, &cookie, sizeof cookie);
    }

    oxm_put_match(msg, &pin->flow_metadata, version);
    ofpbuf_put_zeros(msg, 2);

    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_ofp15_group_mod(enum ofp_version ofp_version,
                               const struct ofputil_group_mod *gm)
{
    struct ofpbuf *b;
    struct ofp15_group_mod *ogm;
    size_t start_ogm;
    struct ofputil_bucket *bucket;
    struct id_pool *bucket_ids = NULL;

    b = ofpraw_alloc(OFPRAW_OFPT15_GROUP_MOD, ofp_version, 0);
    start_ogm = b->size;
    ofpbuf_put_zeros(b, sizeof *ogm);

    LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
        uint32_t bucket_id;

        /* Generate a bucket id if none was supplied */
        if (bucket->bucket_id > OFPG15_BUCKET_MAX) {
            if (!bucket_ids) {
                const struct ofputil_bucket *bkt;

                bucket_ids = id_pool_create(0, OFPG15_BUCKET_MAX + 1);

                /* Mark all bucket_ids that are present in gm
                 * as used in the pool. */
                LIST_FOR_EACH_REVERSE (bkt, list_node, &gm->buckets) {
                    if (bkt == bucket) {
                        break;
                    }
                    if (bkt->bucket_id <= OFPG15_BUCKET_MAX) {
                        id_pool_add(bucket_ids, bkt->bucket_id);
                    }
                }
            }

            if (!id_pool_alloc_id(bucket_ids, &bucket_id)) {
                OVS_NOT_REACHED();
            }
        } else {
            bucket_id = bucket->bucket_id;
        }

        ofputil_put_ofp15_bucket(bucket, bucket_id, gm->type, b, ofp_version);
    }
    ogm = ofpbuf_at_assert(b, start_ogm, sizeof *ogm);
    ogm->command = htons(gm->command);
    ogm->type = gm->type;
    ogm->group_id = htonl(gm->group_id);
    ogm->command_bucket_id = htonl(gm->command_bucket_id);
    ogm->bucket_array_len = htons(b->size - start_ogm - sizeof *ogm);

    /* Add group properties */
    if (gm->props.selection_method[0]) {
        ofputil_put_group_prop_ntr_selection_method(ofp_version, &gm->props, b);
    }

    id_pool_destroy(bucket_ids);
    return b;
}

Project: ovs
File: ofp-util.c

ofputil_encode_packet_in_private(const struct ofputil_packet_in_private *pin,
                                 enum ofputil_protocol protocol,
                                 enum nx_packet_in_format packet_in_format)
{
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);

    struct ofpbuf *msg;
    switch (packet_in_format) {
    case NXPIF_STANDARD:
        switch (protocol) {
        case OFPUTIL_P_OF10_STD:
        case OFPUTIL_P_OF10_STD_TID:
        case OFPUTIL_P_OF10_NXM:
        case OFPUTIL_P_OF10_NXM_TID:
            msg = ofputil_encode_ofp10_packet_in(&pin->public);
            break;

        case OFPUTIL_P_OF11_STD:
            msg = ofputil_encode_ofp11_packet_in(&pin->public);
            break;

        case OFPUTIL_P_OF12_OXM:
        case OFPUTIL_P_OF13_OXM:
        case OFPUTIL_P_OF14_OXM:
        case OFPUTIL_P_OF15_OXM:
        case OFPUTIL_P_OF16_OXM:
            msg = ofputil_encode_ofp12_packet_in(&pin->public, version);
            break;

        default:
            OVS_NOT_REACHED();
        }
        break;

    case NXPIF_NXT_PACKET_IN:
        msg = ofputil_encode_nx_packet_in(&pin->public, version);
        break;

    case NXPIF_NXT_PACKET_IN2:
        return ofputil_encode_nx_packet_in2(pin, version,
                                            pin->public.packet_len);

    default:
        OVS_NOT_REACHED();
    }

    ofpbuf_put(msg, pin->public.packet, pin->public.packet_len);
    ofpmsg_update_length(msg);
    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_packet_out(const struct ofputil_packet_out *po,
                          enum ofputil_protocol protocol)
{
    enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
    struct ofpbuf *msg;
    size_t size;

    size = po->ofpacts_len;
    if (po->buffer_id == UINT32_MAX) {
        size += po->packet_len;
    }

    switch (ofp_version) {
    case OFP10_VERSION: {
        struct ofp10_packet_out *opo;
        size_t actions_ofs;

        msg = ofpraw_alloc(OFPRAW_OFPT10_PACKET_OUT, OFP10_VERSION, size);
        ofpbuf_put_zeros(msg, sizeof *opo);
        actions_ofs = msg->size;
        ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg,
                                     ofp_version);

        opo = msg->msg;
        opo->buffer_id = htonl(po->buffer_id);
        opo->in_port = htons(ofp_to_u16(po->in_port));
        opo->actions_len = htons(msg->size - actions_ofs);
        break;
    }

    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION:
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION: {
        struct ofp11_packet_out *opo;
        size_t len;

        msg = ofpraw_alloc(OFPRAW_OFPT11_PACKET_OUT, ofp_version, size);
        ofpbuf_put_zeros(msg, sizeof *opo);
        len = ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg,
                                           ofp_version);
        opo = msg->msg;
        opo->buffer_id = htonl(po->buffer_id);
        opo->in_port = ofputil_port_to_ofp11(po->in_port);
        opo->actions_len = htons(len);
        break;
    }

    default:
        OVS_NOT_REACHED();
    }

    if (po->buffer_id == UINT32_MAX) {
        ofpbuf_put(msg, po->packet, po->packet_len);
    }

    ofpmsg_update_length(msg);

    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_port_desc_stats_request(enum ofp_version ofp_version,
                                       ofp_port_t port)
{
    struct ofpbuf *request;

    switch (ofp_version) {
    case OFP10_VERSION:
    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION:
    case OFP14_VERSION:
        request = ofpraw_alloc(OFPRAW_OFPST10_PORT_DESC_REQUEST,
                               ofp_version, 0);
        break;
    case OFP15_VERSION:
    case OFP16_VERSION:{
        struct ofp15_port_desc_request *req;
        request = ofpraw_alloc(OFPRAW_OFPST15_PORT_DESC_REQUEST,
                               ofp_version, 0);
        req = ofpbuf_put_zeros(request, sizeof *req);
        req->port_no = ofputil_port_to_ofp11(port);
        break;
    }
    default:
        OVS_NOT_REACHED();
    }

    return request;
}

Project: ovs
File: ofp-util.c

ofputil_encode_port_mod(const struct ofputil_port_mod *pm,
                        enum ofputil_protocol protocol)
{
    enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
    struct ofpbuf *b;

    switch (ofp_version) {
    case OFP10_VERSION: {
        struct ofp10_port_mod *opm;

        b = ofpraw_alloc(OFPRAW_OFPT10_PORT_MOD, ofp_version, 0);
        opm = ofpbuf_put_zeros(b, sizeof *opm);
        opm->port_no = htons(ofp_to_u16(pm->port_no));
        opm->hw_addr = pm->hw_addr;
        opm->config = htonl(pm->config & OFPPC10_ALL);
        opm->mask = htonl(pm->mask & OFPPC10_ALL);
        opm->advertise = netdev_port_features_to_ofp10(pm->advertise);
        break;
    }

    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION: {
        struct ofp11_port_mod *opm;

        b = ofpraw_alloc(OFPRAW_OFPT11_PORT_MOD, ofp_version, 0);
        opm = ofpbuf_put_zeros(b, sizeof *opm);
        opm->port_no = ofputil_port_to_ofp11(pm->port_no);
        opm->hw_addr = pm->hw_addr;
        opm->config = htonl(pm->config & OFPPC11_ALL);
        opm->mask = htonl(pm->mask & OFPPC11_ALL);
        opm->advertise = netdev_port_features_to_ofp11(pm->advertise);
        break;
    }
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION: {
        struct ofp14_port_mod *opm;

        b = ofpraw_alloc(OFPRAW_OFPT14_PORT_MOD, ofp_version, 0);
        opm = ofpbuf_put_zeros(b, sizeof *opm);
        opm->port_no = ofputil_port_to_ofp11(pm->port_no);
        opm->hw_addr = pm->hw_addr;
        opm->config = htonl(pm->config & OFPPC11_ALL);
        opm->mask = htonl(pm->mask & OFPPC11_ALL);

        if (pm->advertise) {
            ofpprop_put_be32(b, OFPPMPT14_ETHERNET,
                             netdev_port_features_to_ofp11(pm->advertise));
        }
        break;
    }
    default:
        OVS_NOT_REACHED();
    }

    return b;
}

Project: ovs
File: ofp-util.c

ofputil_encode_port_status(const struct ofputil_port_status *ps,
                           enum ofputil_protocol protocol)
{
    struct ofp_port_status *ops;
    struct ofpbuf *b;
    enum ofp_version version;
    enum ofpraw raw;

    version = ofputil_protocol_to_ofp_version(protocol);
    switch (version) {
    case OFP10_VERSION:
        raw = OFPRAW_OFPT10_PORT_STATUS;
        break;

    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION:
        raw = OFPRAW_OFPT11_PORT_STATUS;
        break;

    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION:
        raw = OFPRAW_OFPT14_PORT_STATUS;
        break;

    default:
        OVS_NOT_REACHED();
    }

    b = ofpraw_alloc_xid(raw, version, htonl(0), 0);
    ops = ofpbuf_put_zeros(b, sizeof *ops);
    ops->reason = ps->reason;
    ofputil_put_phy_port(version, &ps->desc, b);
    ofpmsg_update_length(b);
    return b;
}

Project: ovs
File: ofp-util.c

ofputil_encode_queue_get_config_request(enum ofp_version version,
                                        ofp_port_t port,
                                        uint32_t queue)
{
    struct ofpbuf *request;

    if (version == OFP10_VERSION) {
        struct ofp10_queue_get_config_request *qgcr10;

        request = ofpraw_alloc(OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST,
                               version, 0);
        qgcr10 = ofpbuf_put_zeros(request, sizeof *qgcr10);
        qgcr10->port = htons(ofp_to_u16(port));
    } else if (version < OFP14_VERSION) {
        struct ofp11_queue_get_config_request *qgcr11;

        request = ofpraw_alloc(OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST,
                               version, 0);
        qgcr11 = ofpbuf_put_zeros(request, sizeof *qgcr11);
        qgcr11->port = ofputil_port_to_ofp11(port);
    } else {
        struct ofp14_queue_desc_request *qdr14;

        request = ofpraw_alloc(OFPRAW_OFPST14_QUEUE_DESC_REQUEST,
                               version, 0);
        qdr14 = ofpbuf_put_zeros(request, sizeof *qdr14);
        qdr14->port = ofputil_port_to_ofp11(port);
        qdr14->queue = htonl(queue);
    }

    return request;
}

Project: ovs
File: ofp-util.c

ofputil_encode_queue_stats_request(enum ofp_version ofp_version,
                                   const struct ofputil_queue_stats_request *oqsr)
{
    struct ofpbuf *request;

    switch (ofp_version) {
    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION:
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION: {
        struct ofp11_queue_stats_request *req;
        request = ofpraw_alloc(OFPRAW_OFPST11_QUEUE_REQUEST, ofp_version, 0);
        req = ofpbuf_put_zeros(request, sizeof *req);
        req->port_no = ofputil_port_to_ofp11(oqsr->port_no);
        req->queue_id = htonl(oqsr->queue_id);
        break;
    }
    case OFP10_VERSION: {
        struct ofp10_queue_stats_request *req;
        request = ofpraw_alloc(OFPRAW_OFPST10_QUEUE_REQUEST, ofp_version, 0);
        req = ofpbuf_put_zeros(request, sizeof *req);
        /* OpenFlow 1.0 needs OFPP_ALL instead of OFPP_ANY */
        req->port_no = htons(ofp_to_u16(oqsr->port_no == OFPP_ANY
                                        ? OFPP_ALL : oqsr->port_no));
        req->queue_id = htonl(oqsr->queue_id);
        break;
    }
    default:
        OVS_NOT_REACHED();
    }

    return request;
}

Project: ovs
File: ofp-util.c

ofputil_encode_resume(const struct ofputil_packet_in *pin,
                      const struct ofpbuf *continuation,
                      enum ofputil_protocol protocol)
{
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
    size_t extra = pin->packet_len + NXM_TYPICAL_LEN + continuation->size;
    struct ofpbuf *msg = ofpraw_alloc_xid(OFPRAW_NXT_RESUME, version,
                                          0, extra);
    ofputil_put_packet_in(pin, version, pin->packet_len, msg);
    ofpprop_put_nested(msg, NXPINT_CONTINUATION, continuation);
    ofpmsg_update_length(msg);
    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_encode_role_reply(const struct ofp_header *request,
                          const struct ofputil_role_request *rr)
{
    struct ofpbuf *buf;
    enum ofpraw raw;

    raw = ofpraw_decode_assert(request);
    if (raw == OFPRAW_OFPT12_ROLE_REQUEST) {
        struct ofp12_role_request *orr;

        buf = ofpraw_alloc_reply(OFPRAW_OFPT12_ROLE_REPLY, request, 0);
        orr = ofpbuf_put_zeros(buf, sizeof *orr);

        orr->role = htonl(rr->role);
        orr->generation_id = htonll(rr->have_generation_id
                                    ? rr->generation_id
                                    : UINT64_MAX);
    } else if (raw == OFPRAW_NXT_ROLE_REQUEST) {
        struct nx_role_request *nrr;

        BUILD_ASSERT(NX_ROLE_OTHER == OFPCR12_ROLE_EQUAL - 1);
        BUILD_ASSERT(NX_ROLE_MASTER == OFPCR12_ROLE_MASTER - 1);
        BUILD_ASSERT(NX_ROLE_SLAVE == OFPCR12_ROLE_SLAVE - 1);

        buf = ofpraw_alloc_reply(OFPRAW_NXT_ROLE_REPLY, request, 0);
        nrr = ofpbuf_put_zeros(buf, sizeof *nrr);
        nrr->role = htonl(rr->role - 1);
    } else {
        OVS_NOT_REACHED();
    }

    return buf;
}

Project: ovs
File: ofp-util.c

ofputil_encode_set_async_config(const struct ofputil_async_cfg *ac,
                                uint32_t oams, enum ofp_version ofp_version)
{
    enum ofpraw raw = (ofp_version >= OFP14_VERSION ? OFPRAW_OFPT14_SET_ASYNC
                       : oams & OAM_EXTENSIONS ? OFPRAW_NXT_SET_ASYNC_CONFIG2
                       : ofp_version >= OFP13_VERSION ? OFPRAW_OFPT13_SET_ASYNC
                       : OFPRAW_NXT_SET_ASYNC_CONFIG);
    struct ofpbuf *request = ofpraw_alloc(raw, ofp_version, 0);
    ofputil_put_async_config__(ac, request,
                               (raw == OFPRAW_OFPT14_SET_ASYNC ||
                                raw == OFPRAW_NXT_SET_ASYNC_CONFIG2),
                               ofp_version, oams);
    return request;
}

Project: ovs
File: ofp-util.c

ofputil_encode_set_config(const struct ofputil_switch_config *config,
                          enum ofp_version version)
{
    struct ofpbuf *b = ofpraw_alloc(OFPRAW_OFPT_SET_CONFIG, version, 0);
    return ofputil_put_switch_config(config, b);
}

Project: ovs
File: ofp-util.c

ofputil_encode_set_protocol(enum ofputil_protocol current,
                            enum ofputil_protocol want,
                            enum ofputil_protocol *next)
{
    enum ofp_version cur_version, want_version;
    enum ofputil_protocol cur_base, want_base;
    bool cur_tid, want_tid;

    cur_version = ofputil_protocol_to_ofp_version(current);
    want_version = ofputil_protocol_to_ofp_version(want);
    if (cur_version != want_version) {
        *next = current;
        return NULL;
    }

    cur_base = ofputil_protocol_to_base(current);
    want_base = ofputil_protocol_to_base(want);
    if (cur_base != want_base) {
        *next = ofputil_protocol_set_base(current, want_base);

        switch (want_base) {
        case OFPUTIL_P_OF10_NXM:
            return ofputil_encode_nx_set_flow_format(NXFF_NXM);

        case OFPUTIL_P_OF10_STD:
            return ofputil_encode_nx_set_flow_format(NXFF_OPENFLOW10);

        case OFPUTIL_P_OF11_STD:
        case OFPUTIL_P_OF12_OXM:
        case OFPUTIL_P_OF13_OXM:
        case OFPUTIL_P_OF14_OXM:
        case OFPUTIL_P_OF15_OXM:
        case OFPUTIL_P_OF16_OXM:
            /* There is only one variant of each OpenFlow 1.1+ protocol, and we
             * verified above that we're not trying to change versions. */
            OVS_NOT_REACHED();

        case OFPUTIL_P_OF10_STD_TID:
        case OFPUTIL_P_OF10_NXM_TID:
            OVS_NOT_REACHED();
        }
    }

    cur_tid = (current & OFPUTIL_P_TID) != 0;
    want_tid = (want & OFPUTIL_P_TID) != 0;
    if (cur_tid != want_tid) {
        *next = ofputil_protocol_set_tid(current, want_tid);
        return ofputil_make_flow_mod_table_id(want_tid);
    }

    ovs_assert(current == want);

    *next = current;
    return NULL;
}

Project: ovs
File: ofp-util.c

ofputil_encode_switch_features(const struct ofputil_switch_features *features,
                               enum ofputil_protocol protocol, ovs_be32 xid)
{
    struct ofp_switch_features *osf;
    struct ofpbuf *b;
    enum ofp_version version;
    enum ofpraw raw;

    version = ofputil_protocol_to_ofp_version(protocol);
    switch (version) {
    case OFP10_VERSION:
        raw = OFPRAW_OFPT10_FEATURES_REPLY;
        break;
    case OFP11_VERSION:
    case OFP12_VERSION:
        raw = OFPRAW_OFPT11_FEATURES_REPLY;
        break;
    case OFP13_VERSION:
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION:
        raw = OFPRAW_OFPT13_FEATURES_REPLY;
        break;
    default:
        OVS_NOT_REACHED();
    }
    b = ofpraw_alloc_xid(raw, version, xid, 0);
    osf = ofpbuf_put_zeros(b, sizeof *osf);
    osf->datapath_id = htonll(features->datapath_id);
    osf->n_buffers = htonl(features->n_buffers);
    osf->n_tables = features->n_tables;

    osf->capabilities = htonl(features->capabilities &
                              ofputil_capabilities_mask(version));
    switch (version) {
    case OFP10_VERSION:
        if (features->capabilities & OFPUTIL_C_STP) {
            osf->capabilities |= htonl(OFPC10_STP);
        }
        osf->actions = ofpact_bitmap_to_openflow(features->ofpacts,
                                                 OFP10_VERSION);
        break;
    case OFP13_VERSION:
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION:
        osf->auxiliary_id = features->auxiliary_id;
        /* fall through */
    case OFP11_VERSION:
    case OFP12_VERSION:
        if (features->capabilities & OFPUTIL_C_GROUP_STATS) {
            osf->capabilities |= htonl(OFPC11_GROUP_STATS);
        }
        break;
    default:
        OVS_NOT_REACHED();
    }

    return b;
}

Project: ovs
File: ofp-util.c

ofputil_encode_table_config(enum ofputil_table_miss miss,
                            enum ofputil_table_eviction eviction,
                            enum ofputil_table_vacancy vacancy,
                            enum ofp_version version)
{
    uint32_t config = 0;
    /* Search for "OFPTC_* Table Configuration" in the documentation for more
     * information on the crazy evolution of this field. */
    switch (version) {
    case OFP10_VERSION:
        /* OpenFlow 1.0 didn't have such a field, any value ought to do. */
        return htonl(0);

    case OFP11_VERSION:
    case OFP12_VERSION:
        /* OpenFlow 1.1 and 1.2 define only OFPTC11_TABLE_MISS_*. */
        switch (miss) {
        case OFPUTIL_TABLE_MISS_DEFAULT:
            /* Really this shouldn't be used for encoding (the caller should
             * provide a specific value) but I can't imagine that defaulting to
             * the fall-through case here will hurt. */
        case OFPUTIL_TABLE_MISS_CONTROLLER:
        default:
            return htonl(OFPTC11_TABLE_MISS_CONTROLLER);
        case OFPUTIL_TABLE_MISS_CONTINUE:
            return htonl(OFPTC11_TABLE_MISS_CONTINUE);
        case OFPUTIL_TABLE_MISS_DROP:
            return htonl(OFPTC11_TABLE_MISS_DROP);
        }
        OVS_NOT_REACHED();

    case OFP13_VERSION:
        /* OpenFlow 1.3 removed OFPTC11_TABLE_MISS_* and didn't define any new
         * flags, so this is correct. */
        return htonl(0);

    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION:
        /* OpenFlow 1.4 introduced OFPTC14_EVICTION and
         * OFPTC14_VACANCY_EVENTS. */
        if (eviction == OFPUTIL_TABLE_EVICTION_ON) {
            config |= OFPTC14_EVICTION;
        }
        if (vacancy == OFPUTIL_TABLE_VACANCY_ON) {
            config |= OFPTC14_VACANCY_EVENTS;
        }
        return htonl(config);
    }

    OVS_NOT_REACHED();
}

Project: ovs
File: ofp-util.c

ofputil_encode_table_desc_request(enum ofp_version ofp_version)
{
    struct ofpbuf *request = NULL;

    if (ofp_version >= OFP14_VERSION) {
        request = ofpraw_alloc(OFPRAW_OFPST14_TABLE_DESC_REQUEST,
                               ofp_version, 0);
    } else {
        ovs_fatal(0, "dump-table-desc needs OpenFlow 1.4 or later "
                  "(\'-O OpenFlow14\')");
    }

    return request;
}

Project: ovs
File: ofp-util.c

ofputil_encode_table_features_request(enum ofp_version ofp_version)
{
    struct ofpbuf *request = NULL;

    switch (ofp_version) {
    case OFP10_VERSION:
    case OFP11_VERSION:
    case OFP12_VERSION:
        ovs_fatal(0, "dump-table-features needs OpenFlow 1.3 or later "
                     "(\'-O OpenFlow13\')");
    case OFP13_VERSION:
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION:
        request = ofpraw_alloc(OFPRAW_OFPST13_TABLE_FEATURES_REQUEST,
                               ofp_version, 0);
        break;
    default:
        OVS_NOT_REACHED();
    }

    return request;
}

Project: ovs
File: ofp-util.c

ofputil_encode_table_stats_reply(const struct ofp_header *request)
{
    return ofpraw_alloc_stats_reply(request, 0);
}

Project: ovs
File: ofp-util.c

ofputil_encode_table_status(const struct ofputil_table_status *ts,
                            enum ofputil_protocol protocol)
{
    enum ofp_version version;
    struct ofpbuf *b;

    version = ofputil_protocol_to_ofp_version(protocol);
    if (version >= OFP14_VERSION) {
        enum ofpraw raw;
        struct ofp14_table_status *ots;

        raw = OFPRAW_OFPT14_TABLE_STATUS;
        b = ofpraw_alloc_xid(raw, version, htonl(0), 0);
        ots = ofpbuf_put_zeros(b, sizeof *ots);
        ots->reason = ts->reason;
        ofputil_put_ofp14_table_desc(&ts->desc, b, version);
        ofpmsg_update_length(b);
        return b;
    } else {
        return NULL;
    }
}

Project: ovs
File: ofp-util.c

ofputil_encode_tlv_table_mod(enum ofp_version ofp_version,
                                struct ofputil_tlv_table_mod *ttm)
{
    struct ofpbuf *b;
    struct nx_tlv_table_mod *nx_ttm;

    b = ofpraw_alloc(OFPRAW_NXT_TLV_TABLE_MOD, ofp_version, 0);
    nx_ttm = ofpbuf_put_zeros(b, sizeof *nx_ttm);
    nx_ttm->command = htons(ttm->command);
    encode_tlv_table_mappings(b, &ttm->mappings);

    return b;
}

Project: ovs
File: ofp-util.c

ofputil_encode_tlv_table_reply(const struct ofp_header *oh,
                                  struct ofputil_tlv_table_reply *ttr)
{
    struct ofpbuf *b;
    struct nx_tlv_table_reply *nx_ttr;

    b = ofpraw_alloc_reply(OFPRAW_NXT_TLV_TABLE_REPLY, oh, 0);
    nx_ttr = ofpbuf_put_zeros(b, sizeof *nx_ttr);
    nx_ttr->max_option_space = htonl(ttr->max_option_space);
    nx_ttr->max_fields = htons(ttr->max_fields);

    encode_tlv_table_mappings(b, &ttr->mappings);

    return b;
}

Project: ovs
File: ofp-util.c

ofputil_format_group(uint32_t group_id, struct ds *s)
{
    char name[MAX_GROUP_NAME_LEN];

    ofputil_group_to_string(group_id, name, sizeof name);
    ds_put_cstr(s, name);
}

Project: ovs
File: ofp-util.c

ofputil_format_port(ofp_port_t port, struct ds *s)
{
    char name[OFP_MAX_PORT_NAME_LEN];

    ofputil_port_to_string(port, name, sizeof name);
    ds_put_cstr(s, name);
}

Project: ovs
File: ofp-util.c

ofputil_format_version(struct ds *msg, enum ofp_version version)
{
    ds_put_format(msg, "0x%02x", version);
}

Project: ovs
File: ofp-util.c

ofputil_format_version_bitmap(struct ds *msg, uint32_t bitmap)
{
    ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version);
}

Project: ovs
File: ofp-util.c

ofputil_format_version_bitmap__(struct ds *msg, uint32_t bitmap,
                                void (*format_version)(struct ds *msg,
                                                       enum ofp_version))
{
    while (bitmap) {
        format_version(msg, raw_ctz(bitmap));
        bitmap = zero_rightmost_1bit(bitmap);
        if (bitmap) {
            ds_put_cstr(msg, ", ");
        }
    }
}

Project: ovs
File: ofp-util.c

ofputil_format_version_bitmap_names(struct ds *msg, uint32_t bitmap)
{
    ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version_name);
}

Project: ovs
File: ofp-util.c

ofputil_format_version_name(struct ds *msg, enum ofp_version version)
{
    ds_put_cstr(msg, ofputil_version_to_string(version));
}

Project: ovs
File: ofp-util.c

ofputil_frag_handling_from_string(const char *s,
                                  enum ofputil_frag_handling *frag)
{
    if (!strcasecmp(s, "normal")) {
        *frag = OFPUTIL_FRAG_NORMAL;
    } else if (!strcasecmp(s, "drop")) {
        *frag = OFPUTIL_FRAG_DROP;
    } else if (!strcasecmp(s, "reassemble")) {
        *frag = OFPUTIL_FRAG_REASM;
    } else if (!strcasecmp(s, "nx-match")) {
        *frag = OFPUTIL_FRAG_NX_MATCH;
    } else {
        return false;
    }
    return true;
}

Project: ovs
File: ofp-util.c

ofputil_frag_handling_to_string(enum ofputil_frag_handling frag)
{
    switch (frag) {
    case OFPUTIL_FRAG_NORMAL:   return "normal";
    case OFPUTIL_FRAG_DROP:     return "drop";
    case OFPUTIL_FRAG_REASM:    return "reassemble";
    case OFPUTIL_FRAG_NX_MATCH: return "nx-match";
    }

    OVS_NOT_REACHED();
}

Project: ovs
File: ofp-util.c

ofputil_free_bundle_msgs(struct ofputil_bundle_msg *bms, size_t n_bms)
{
    for (size_t i = 0; i < n_bms; i++) {
        switch ((int)bms[i].type) {
        case OFPTYPE_FLOW_MOD:
            free(CONST_CAST(struct ofpact *, bms[i].fm.ofpacts));
            break;
        case OFPTYPE_GROUP_MOD:
            ofputil_uninit_group_mod(&bms[i].gm);
            break;
        case OFPTYPE_PACKET_OUT:
            free(bms[i].po.ofpacts);
            free(CONST_CAST(void *, bms[i].po.packet));
            break;
        default:
            break;
        }
    }
    free(bms);
}

Project: ovs
File: ofp-util.c

ofputil_group_bucket_counters_to_ofp11(const struct ofputil_group_stats *gs,
                                    struct ofp11_bucket_counter bucket_cnts[])
{
    int i;

    for (i = 0; i < gs->n_buckets; i++) {
       bucket_cnts[i].packet_count = htonll(gs->bucket_stats[i].packet_count);
       bucket_cnts[i].byte_count = htonll(gs->bucket_stats[i].byte_count);
    }
}

Project: ovs
File: ofp-util.c

ofputil_group_properties_copy(struct ofputil_group_props *to,
                              const struct ofputil_group_props *from)
{
    *to = *from;
    to->fields.values = xmemdup(from->fields.values, from->fields.values_size);
}

Project: ovs
File: ofp-util.c

ofputil_group_properties_destroy(struct ofputil_group_props *gp)
{
    free(gp->fields.values);
}

Project: ovs
File: ofp-util.c

ofputil_group_stats_to_ofp11(const struct ofputil_group_stats *gs,
                             struct ofp11_group_stats *gs11, size_t length,
                             struct ofp11_bucket_counter bucket_cnts[])
{
    memset(gs11, 0, sizeof *gs11);
    gs11->length = htons(length);
    gs11->group_id = htonl(gs->group_id);
    gs11->ref_count = htonl(gs->ref_count);
    gs11->packet_count = htonll(gs->packet_count);
    gs11->byte_count = htonll(gs->byte_count);
    ofputil_group_bucket_counters_to_ofp11(gs, bucket_cnts);
}

Project: ovs
File: ofp-util.c

ofputil_group_to_string(uint32_t group_id,
                        char namebuf[MAX_GROUP_NAME_LEN + 1], size_t bufsize)
{
    switch (group_id) {
    case OFPG_ALL:
        ovs_strlcpy(namebuf, "ALL", bufsize);
        break;

    case OFPG_ANY:
        ovs_strlcpy(namebuf, "ANY", bufsize);
        break;

    default:
        snprintf(namebuf, bufsize, "%"PRIu32, group_id);
        break;
    }
}

Project: ovs
File: ofp-util.c

ofputil_init_group_properties(struct ofputil_group_props *gp)
{
    memset(gp, 0, sizeof *gp);
}

Project: ovs
File: ofp-util.c

ofputil_ipfix_stats_from_nx(struct ofputil_ipfix_stats *is,
                            const struct nx_ipfix_stats_reply *reply)
{
    is->collector_set_id = ntohl(reply->collector_set_id);
    is->total_flows = ntohll(reply->total_flows);
    is->current_flows = ntohll(reply->current_flows);
    is->pkts = ntohll(reply->pkts);
    is->ipv4_pkts = ntohll(reply->ipv4_pkts);
    is->ipv6_pkts = ntohll(reply->ipv6_pkts);
    is->error_pkts = ntohll(reply->error_pkts);
    is->ipv4_error_pkts = ntohll(reply->ipv4_error_pkts);
    is->ipv6_error_pkts = ntohll(reply->ipv6_error_pkts);
    is->tx_pkts = ntohll(reply->tx_pkts);
    is->tx_errors = ntohll(reply->tx_errors);

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_ipfix_stats_to_reply(const struct ofputil_ipfix_stats *ois,
                            struct nx_ipfix_stats_reply *reply)
{
    reply->collector_set_id = htonl(ois->collector_set_id);
    reply->total_flows = htonll(ois->total_flows);
    reply->current_flows = htonll(ois->current_flows);
    reply->pkts = htonll(ois->pkts);
    reply->ipv4_pkts = htonll(ois->ipv4_pkts);
    reply->ipv6_pkts = htonll(ois->ipv6_pkts);
    reply->error_pkts = htonll(ois->error_pkts);
    reply->ipv4_error_pkts = htonll(ois->ipv4_error_pkts);
    reply->ipv6_error_pkts = htonll(ois->ipv6_error_pkts);
    reply->tx_pkts = htonll(ois->tx_pkts);
    reply->tx_errors = htonll(ois->tx_errors);
    memset(reply->pad, 0, sizeof reply->pad);
}

Project: ovs
File: ofp-util.c

ofputil_is_bundlable(enum ofptype type)
{
    switch (type) {
        /* Minimum required by OpenFlow 1.4. */
    case OFPTYPE_PORT_MOD:
    case OFPTYPE_FLOW_MOD:
        /* Other supported types. */
    case OFPTYPE_GROUP_MOD:
    case OFPTYPE_PACKET_OUT:
        return true;

        /* Nice to have later. */
    case OFPTYPE_FLOW_MOD_TABLE_ID:
    case OFPTYPE_TABLE_MOD:
    case OFPTYPE_METER_MOD:
    case OFPTYPE_NXT_TLV_TABLE_MOD:

        /* Not to be bundlable. */
    case OFPTYPE_ECHO_REQUEST:
    case OFPTYPE_FEATURES_REQUEST:
    case OFPTYPE_GET_CONFIG_REQUEST:
    case OFPTYPE_SET_CONFIG:
    case OFPTYPE_BARRIER_REQUEST:
    case OFPTYPE_ROLE_REQUEST:
    case OFPTYPE_ECHO_REPLY:
    case OFPTYPE_SET_FLOW_FORMAT:
    case OFPTYPE_SET_PACKET_IN_FORMAT:
    case OFPTYPE_SET_CONTROLLER_ID:
    case OFPTYPE_FLOW_AGE:
    case OFPTYPE_FLOW_MONITOR_CANCEL:
    case OFPTYPE_SET_ASYNC_CONFIG:
    case OFPTYPE_GET_ASYNC_REQUEST:
    case OFPTYPE_DESC_STATS_REQUEST:
    case OFPTYPE_FLOW_STATS_REQUEST:
    case OFPTYPE_AGGREGATE_STATS_REQUEST:
    case OFPTYPE_TABLE_STATS_REQUEST:
    case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
    case OFPTYPE_TABLE_DESC_REQUEST:
    case OFPTYPE_PORT_STATS_REQUEST:
    case OFPTYPE_QUEUE_STATS_REQUEST:
    case OFPTYPE_PORT_DESC_STATS_REQUEST:
    case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
    case OFPTYPE_METER_STATS_REQUEST:
    case OFPTYPE_METER_CONFIG_STATS_REQUEST:
    case OFPTYPE_METER_FEATURES_STATS_REQUEST:
    case OFPTYPE_GROUP_STATS_REQUEST:
    case OFPTYPE_GROUP_DESC_STATS_REQUEST:
    case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
    case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
    case OFPTYPE_BUNDLE_CONTROL:
    case OFPTYPE_BUNDLE_ADD_MESSAGE:
    case OFPTYPE_HELLO:
    case OFPTYPE_ERROR:
    case OFPTYPE_FEATURES_REPLY:
    case OFPTYPE_GET_CONFIG_REPLY:
    case OFPTYPE_PACKET_IN:
    case OFPTYPE_FLOW_REMOVED:
    case OFPTYPE_PORT_STATUS:
    case OFPTYPE_BARRIER_REPLY:
    case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
    case OFPTYPE_DESC_STATS_REPLY:
    case OFPTYPE_FLOW_STATS_REPLY:
    case OFPTYPE_QUEUE_STATS_REPLY:
    case OFPTYPE_PORT_STATS_REPLY:
    case OFPTYPE_TABLE_STATS_REPLY:
    case OFPTYPE_AGGREGATE_STATS_REPLY:
    case OFPTYPE_PORT_DESC_STATS_REPLY:
    case OFPTYPE_ROLE_REPLY:
    case OFPTYPE_FLOW_MONITOR_PAUSED:
    case OFPTYPE_FLOW_MONITOR_RESUMED:
    case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
    case OFPTYPE_GET_ASYNC_REPLY:
    case OFPTYPE_GROUP_STATS_REPLY:
    case OFPTYPE_GROUP_DESC_STATS_REPLY:
    case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
    case OFPTYPE_METER_STATS_REPLY:
    case OFPTYPE_METER_CONFIG_STATS_REPLY:
    case OFPTYPE_METER_FEATURES_STATS_REPLY:
    case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
    case OFPTYPE_TABLE_DESC_REPLY:
    case OFPTYPE_ROLE_STATUS:
    case OFPTYPE_REQUESTFORWARD:
    case OFPTYPE_TABLE_STATUS:
    case OFPTYPE_NXT_TLV_TABLE_REQUEST:
    case OFPTYPE_NXT_TLV_TABLE_REPLY:
    case OFPTYPE_NXT_RESUME:
    case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST:
    case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY:
    case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
    case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
    case OFPTYPE_CT_FLUSH_ZONE:
        break;
    }

    return false;
}

Project: ovs
File: ofp-util.c

ofputil_make_flow_mod_table_id(bool flow_mod_table_id)
{
    struct nx_flow_mod_table_id *nfmti;
    struct ofpbuf *msg;

    msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MOD_TABLE_ID, OFP10_VERSION, 0);
    nfmti = ofpbuf_put_zeros(msg, sizeof *nfmti);
    nfmti->set = flow_mod_table_id;
    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_make_set_packet_in_format(enum ofp_version ofp_version,
                                  enum nx_packet_in_format packet_in_format)
{
    struct nx_set_packet_in_format *spif;
    struct ofpbuf *msg;

    msg = ofpraw_alloc(OFPRAW_NXT_SET_PACKET_IN_FORMAT, ofp_version, 0);
    spif = ofpbuf_put_zeros(msg, sizeof *spif);
    spif->format = htonl(packet_in_format);

    return msg;
}

Project: ovs
File: ofp-util.c

ofputil_match_from_ofp10_match(const struct ofp10_match *ofmatch,
                               struct match *match)
{
    uint32_t ofpfw = ntohl(ofmatch->wildcards) & OFPFW10_ALL;

    /* Initialize match->wc. */
    memset(&match->flow, 0, sizeof match->flow);
    ofputil_wildcard_from_ofpfw10(ofpfw, &match->wc);
    memset(&match->tun_md, 0, sizeof match->tun_md);

    /* Initialize most of match->flow. */
    match->flow.nw_src = ofmatch->nw_src;
    match->flow.nw_dst = ofmatch->nw_dst;
    match->flow.in_port.ofp_port = u16_to_ofp(ntohs(ofmatch->in_port));
    match->flow.dl_type = ofputil_dl_type_from_openflow(ofmatch->dl_type);
    match->flow.tp_src = ofmatch->tp_src;
    match->flow.tp_dst = ofmatch->tp_dst;
    match->flow.dl_src = ofmatch->dl_src;
    match->flow.dl_dst = ofmatch->dl_dst;
    match->flow.nw_tos = ofmatch->nw_tos & IP_DSCP_MASK;
    match->flow.nw_proto = ofmatch->nw_proto;

    /* Translate VLANs. */
    if (!(ofpfw & OFPFW10_DL_VLAN) &&
        ofmatch->dl_vlan == htons(OFP10_VLAN_NONE)) {
        /* Match only packets without 802.1Q header.
         *
         * When OFPFW10_DL_VLAN_PCP is wildcarded, this is obviously correct.
         *
         * If OFPFW10_DL_VLAN_PCP is matched, the flow match is contradictory,
         * because we can't have a specific PCP without an 802.1Q header.
         * However, older versions of OVS treated this as matching packets
         * withut an 802.1Q header, so we do here too. */
        match->flow.vlan_tci = htons(0);
        match->wc.masks.vlan_tci = htons(0xffff);
    } else {
        ovs_be16 vid, pcp, tci;
        uint16_t hpcp;

        vid = ofmatch->dl_vlan & htons(VLAN_VID_MASK);
        hpcp = (ofmatch->dl_vlan_pcp << VLAN_PCP_SHIFT) & VLAN_PCP_MASK;
        pcp = htons(hpcp);
        tci = vid | pcp | htons(VLAN_CFI);
        match->flow.vlan_tci = tci & match->wc.masks.vlan_tci;
    }

    /* Clean up. */
    match_zero_wildcarded_fields(match);
}

Project: ovs
File: ofp-util.c

ofputil_match_to_ofp10_match(const struct match *match,
                             struct ofp10_match *ofmatch)
{
    const struct flow_wildcards *wc = &match->wc;
    uint32_t ofpfw;

    /* Figure out most OpenFlow wildcards. */
    ofpfw = 0;
    if (!wc->masks.in_port.ofp_port) {
        ofpfw |= OFPFW10_IN_PORT;
    }
    if (!wc->masks.dl_type) {
        ofpfw |= OFPFW10_DL_TYPE;
    }
    if (!wc->masks.nw_proto) {
        ofpfw |= OFPFW10_NW_PROTO;
    }
    ofpfw |= (ofputil_netmask_to_wcbits(wc->masks.nw_src)
              << OFPFW10_NW_SRC_SHIFT);
    ofpfw |= (ofputil_netmask_to_wcbits(wc->masks.nw_dst)
              << OFPFW10_NW_DST_SHIFT);
    if (!(wc->masks.nw_tos & IP_DSCP_MASK)) {
        ofpfw |= OFPFW10_NW_TOS;
    }
    if (!wc->masks.tp_src) {
        ofpfw |= OFPFW10_TP_SRC;
    }
    if (!wc->masks.tp_dst) {
        ofpfw |= OFPFW10_TP_DST;
    }
    if (eth_addr_is_zero(wc->masks.dl_src)) {
        ofpfw |= OFPFW10_DL_SRC;
    }
    if (eth_addr_is_zero(wc->masks.dl_dst)) {
        ofpfw |= OFPFW10_DL_DST;
    }

    /* Translate VLANs. */
    ofmatch->dl_vlan = htons(0);
    ofmatch->dl_vlan_pcp = 0;
    if (match->wc.masks.vlan_tci == htons(0)) {
        ofpfw |= OFPFW10_DL_VLAN | OFPFW10_DL_VLAN_PCP;
    } else if (match->wc.masks.vlan_tci & htons(VLAN_CFI)
               && !(match->flow.vlan_tci & htons(VLAN_CFI))) {
        ofmatch->dl_vlan = htons(OFP10_VLAN_NONE);
    } else {
        if (!(match->wc.masks.vlan_tci & htons(VLAN_VID_MASK))) {
            ofpfw |= OFPFW10_DL_VLAN;
        } else {
            ofmatch->dl_vlan = htons(vlan_tci_to_vid(match->flow.vlan_tci));
        }

        if (!(match->wc.masks.vlan_tci & htons(VLAN_PCP_MASK))) {
            ofpfw |= OFPFW10_DL_VLAN_PCP;
        } else {
            ofmatch->dl_vlan_pcp = vlan_tci_to_pcp(match->flow.vlan_tci);
        }
    }

    /* Compose most of the match structure. */
    ofmatch->wildcards = htonl(ofpfw);
    ofmatch->in_port = htons(ofp_to_u16(match->flow.in_port.ofp_port));
    ofmatch->dl_src = match->flow.dl_src;
    ofmatch->dl_dst = match->flow.dl_dst;
    ofmatch->dl_type = ofputil_dl_type_to_openflow(match->flow.dl_type);
    ofmatch->nw_src = match->flow.nw_src;
    ofmatch->nw_dst = match->flow.nw_dst;
    ofmatch->nw_tos = match->flow.nw_tos & IP_DSCP_MASK;
    ofmatch->nw_proto = match->flow.nw_proto;
    ofmatch->tp_src = match->flow.tp_src;
    ofmatch->tp_dst = match->flow.tp_dst;
    memset(ofmatch->pad1, '\0', sizeof ofmatch->pad1);
    memset(ofmatch->pad2, '\0', sizeof ofmatch->pad2);
}

Project: ovs
File: ofp-util.c

ofputil_match_typical_len(enum ofputil_protocol protocol)
{
    switch (protocol) {
    case OFPUTIL_P_OF10_STD:
    case OFPUTIL_P_OF10_STD_TID:
        return sizeof(struct ofp10_match);

    case OFPUTIL_P_OF10_NXM:
    case OFPUTIL_P_OF10_NXM_TID:
        return NXM_TYPICAL_LEN;

    case OFPUTIL_P_OF11_STD:
        return sizeof(struct ofp11_match);

    case OFPUTIL_P_OF12_OXM:
    case OFPUTIL_P_OF13_OXM:
    case OFPUTIL_P_OF14_OXM:
    case OFPUTIL_P_OF15_OXM:
    case OFPUTIL_P_OF16_OXM:
        return NXM_TYPICAL_LEN;

    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_netmask_to_wcbits(ovs_be32 netmask)
{
    return 32 - ip_count_cidr_bits(netmask);
}

Project: ovs
File: ofp-util.c

ofputil_normalize_match(struct match *match)
{
    ofputil_normalize_match__(match, true);
}

Project: ovs
File: ofp-util.c

ofputil_normalize_match__(struct match *match, bool may_log)
{
    enum {
        MAY_NW_ADDR     = 1 << 0, /* nw_src, nw_dst */
        MAY_TP_ADDR     = 1 << 1, /* tp_src, tp_dst */
        MAY_NW_PROTO    = 1 << 2, /* nw_proto */
        MAY_IPVx        = 1 << 3, /* tos, frag, ttl */
        MAY_ARP_SHA     = 1 << 4, /* arp_sha */
        MAY_ARP_THA     = 1 << 5, /* arp_tha */
        MAY_IPV6        = 1 << 6, /* ipv6_src, ipv6_dst, ipv6_label */
        MAY_ND_TARGET   = 1 << 7, /* nd_target */
        MAY_MPLS        = 1 << 8, /* mpls label and tc */
    } may_match;

    struct flow_wildcards wc;

    /* Figure out what fields may be matched. */
    if (match->flow.dl_type == htons(ETH_TYPE_IP)) {
        may_match = MAY_NW_PROTO | MAY_IPVx | MAY_NW_ADDR;
        if (match->flow.nw_proto == IPPROTO_TCP ||
            match->flow.nw_proto == IPPROTO_UDP ||
            match->flow.nw_proto == IPPROTO_SCTP ||
            match->flow.nw_proto == IPPROTO_ICMP) {
            may_match |= MAY_TP_ADDR;
        }
    } else if (match->flow.dl_type == htons(ETH_TYPE_IPV6)) {
        may_match = MAY_NW_PROTO | MAY_IPVx | MAY_IPV6;
        if (match->flow.nw_proto == IPPROTO_TCP ||
            match->flow.nw_proto == IPPROTO_UDP ||
            match->flow.nw_proto == IPPROTO_SCTP) {
            may_match |= MAY_TP_ADDR;
        } else if (match->flow.nw_proto == IPPROTO_ICMPV6) {
            may_match |= MAY_TP_ADDR;
            if (match->flow.tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
                may_match |= MAY_ND_TARGET | MAY_ARP_SHA;
            } else if (match->flow.tp_src == htons(ND_NEIGHBOR_ADVERT)) {
                may_match |= MAY_ND_TARGET | MAY_ARP_THA;
            }
        }
    } else if (match->flow.dl_type == htons(ETH_TYPE_ARP) ||
               match->flow.dl_type == htons(ETH_TYPE_RARP)) {
        may_match = MAY_NW_PROTO | MAY_NW_ADDR | MAY_ARP_SHA | MAY_ARP_THA;
    } else if (eth_type_mpls(match->flow.dl_type)) {
        may_match = MAY_MPLS;
    } else {
        may_match = 0;
    }

    /* Clear the fields that may not be matched. */
    wc = match->wc;
    if (!(may_match & MAY_NW_ADDR)) {
        wc.masks.nw_src = wc.masks.nw_dst = htonl(0);
    }
    if (!(may_match & MAY_TP_ADDR)) {
        wc.masks.tp_src = wc.masks.tp_dst = htons(0);
    }
    if (!(may_match & MAY_NW_PROTO)) {
        wc.masks.nw_proto = 0;
    }
    if (!(may_match & MAY_IPVx)) {
        wc.masks.nw_tos = 0;
        wc.masks.nw_ttl = 0;
    }
    if (!(may_match & MAY_ARP_SHA)) {
        WC_UNMASK_FIELD(&wc, arp_sha);
    }
    if (!(may_match & MAY_ARP_THA)) {
        WC_UNMASK_FIELD(&wc, arp_tha);
    }
    if (!(may_match & MAY_IPV6)) {
        wc.masks.ipv6_src = wc.masks.ipv6_dst = in6addr_any;
        wc.masks.ipv6_label = htonl(0);
    }
    if (!(may_match & MAY_ND_TARGET)) {
        wc.masks.nd_target = in6addr_any;
    }
    if (!(may_match & MAY_MPLS)) {
        memset(wc.masks.mpls_lse, 0, sizeof wc.masks.mpls_lse);
    }

    /* Log any changes. */
    if (!flow_wildcards_equal(&wc, &match->wc)) {
        bool log = may_log && !VLOG_DROP_INFO(&bad_ofmsg_rl);
        char *pre = log ? match_to_string(match, OFP_DEFAULT_PRIORITY) : NULL;

        match->wc = wc;
        match_zero_wildcarded_fields(match);

        if (log) {
            char *post = match_to_string(match, OFP_DEFAULT_PRIORITY);
            VLOG_INFO("normalization changed ofp_match, details:");
            VLOG_INFO(" pre: %s", pre);
            VLOG_INFO("post: %s", post);
            free(pre);
            free(post);
        }
    }
}

Project: ovs
File: ofp-util.c

ofputil_normalize_match_quiet(struct match *match)
{
    ofputil_normalize_match__(match, false);
}

Project: ovs
File: ofp-util.c

ofputil_nx_flow_format_is_valid(enum nx_flow_format flow_format)
{
    return ofputil_nx_flow_format_to_protocol(flow_format) != 0;
}

Project: ovs
File: ofp-util.c

ofputil_nx_flow_format_to_protocol(enum nx_flow_format flow_format)
{
    switch (flow_format) {
    case NXFF_OPENFLOW10:
        return OFPUTIL_P_OF10_STD;

    case NXFF_NXM:
        return OFPUTIL_P_OF10_NXM;

    default:
        return 0;
    }
}

Project: ovs
File: ofp-util.c

ofputil_nx_flow_format_to_string(enum nx_flow_format flow_format)
{
    switch (flow_format) {
    case NXFF_OPENFLOW10:
        return "openflow10";
    case NXFF_NXM:
        return "nxm";
    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_packet_in_format_from_string(const char *s)
{
    return (!strcmp(s, "standard") || !strcmp(s, "openflow10")
            ? NXPIF_STANDARD
            : !strcmp(s, "nxt_packet_in") || !strcmp(s, "nxm")
            ? NXPIF_NXT_PACKET_IN
            : !strcmp(s, "nxt_packet_in2")
            ? NXPIF_NXT_PACKET_IN2
            : -1);
}

Project: ovs
File: ofp-util.c

ofputil_packet_in_format_is_valid(enum nx_packet_in_format packet_in_format)
{
    switch (packet_in_format) {
    case NXPIF_STANDARD:
    case NXPIF_NXT_PACKET_IN:
    case NXPIF_NXT_PACKET_IN2:
        return true;
    }

    return false;
}

Project: ovs
File: ofp-util.c

ofputil_packet_in_format_to_string(enum nx_packet_in_format packet_in_format)
{
    switch (packet_in_format) {
    case NXPIF_STANDARD:
        return "standard";
    case NXPIF_NXT_PACKET_IN:
        return "nxt_packet_in";
    case NXPIF_NXT_PACKET_IN2:
        return "nxt_packet_in2";
    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_packet_in_private_destroy(struct ofputil_packet_in_private *pin)
{
    if (pin) {
        free(pin->stack);
        free(pin->actions);
        free(pin->action_set);
    }
}

Project: ovs
File: ofp-util.c

ofputil_packet_in_reason_from_string(const char *s,
                                     enum ofp_packet_in_reason *reason)
{
    int i;

    for (i = 0; i < OFPR_N_REASONS; i++) {
        char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE];
        const char *reason_s;

        reason_s = ofputil_packet_in_reason_to_string(i, reasonbuf,
                                                      sizeof reasonbuf);
        if (!strcasecmp(s, reason_s)) {
            *reason = i;
            return true;
        }
    }
    return false;
}

Project: ovs
File: ofp-util.c

ofputil_packet_in_reason_to_string(enum ofp_packet_in_reason reason,
                                   char *reasonbuf, size_t bufsize)
{
    switch (reason) {
    case OFPR_NO_MATCH:
        return "no_match";
    case OFPR_ACTION:
        return "action";
    case OFPR_INVALID_TTL:
        return "invalid_ttl";
    case OFPR_ACTION_SET:
        return "action_set";
    case OFPR_GROUP:
        return "group";
    case OFPR_PACKET_OUT:
        return "packet_out";
    case OFPR_EXPLICIT_MISS:
    case OFPR_IMPLICIT_MISS:
        return "";

    case OFPR_N_REASONS:
    default:
        snprintf(reasonbuf, bufsize, "%d", (int) reason);
        return reasonbuf;
    }
}

Project: ovs
File: ofp-util.c

ofputil_parse_key_value(char **stringp, char **keyp, char **valuep)
{
    /* Skip white space and delimiters.  If that brings us to the end of the
     * input string, we are done and there are no more key-value pairs. */
    *stringp += strspn(*stringp, ", \t\r\n");
    if (**stringp == '\0') {
        *keyp = *valuep = NULL;
        return false;
    }

    /* Extract the key and the delimiter that ends the key-value pair or begins
     * the value.  Advance the input position past the key and delimiter. */
    char *key = *stringp;
    size_t key_len = strcspn(key, ":=(, \t\r\n");
    char key_delim = key[key_len];
    key[key_len] = '\0';
    *stringp += key_len + (key_delim != '\0');

    /* Figure out what delimiter ends the value:
     *
     *     - If key_delim is ":" or "=", the value extends until white space
     *       or a comma.
     *
     *     - If key_delim is "(", the value extends until ")".
     *
     * If there is no value, we are done. */
    const char *value_delims;
    if (key_delim == ':' || key_delim == '=') {
        value_delims = ", \t\r\n";
    } else if (key_delim == '(') {
        value_delims = ")";
    } else {
        *keyp = key;
        *valuep = key + key_len; /* Empty string. */
        return true;
    }

    /* Extract the value.  Advance the input position past the value and
     * delimiter. */
    char *value = *stringp;
    size_t value_len = parse_value(value, value_delims);
    char value_delim = value[value_len];
    value[value_len] = '\0';
    *stringp += value_len + (value_delim != '\0');

    *keyp = key;
    *valuep = value;
    return true;
}

Project: ovs
File: ofp-util.c

ofputil_port_from_ofp11(ovs_be32 ofp11_port, ofp_port_t *ofp10_port)
{
    uint32_t ofp11_port_h = ntohl(ofp11_port);

    if (ofp11_port_h < ofp_to_u16(OFPP_MAX)) {
        *ofp10_port = u16_to_ofp(ofp11_port_h);
        return 0;
    } else if (ofp11_port_h >= ofp11_to_u32(OFPP11_MAX)) {
        *ofp10_port = u16_to_ofp(ofp11_port_h - OFPP11_OFFSET);
        return 0;
    } else {
        *ofp10_port = OFPP_NONE;
        VLOG_WARN_RL(&bad_ofmsg_rl, "port %"PRIu32" is outside the supported "
                     "range 0 through %d or 0x%"PRIx32" through 0x%"PRIx32,
                     ofp11_port_h, ofp_to_u16(OFPP_MAX) - 1,
                     ofp11_to_u32(OFPP11_MAX), UINT32_MAX);
        return OFPERR_OFPBAC_BAD_OUT_PORT;
    }
}

Project: ovs
File: ofp-util.c

ofputil_port_from_string(const char *s, ofp_port_t *portp)
{
    unsigned int port32; /* int is at least 32 bits wide. */

    if (*s == '-') {
        VLOG_WARN("Negative value %s is not a valid port number.", s);
        return false;
    }
    *portp = 0;
    if (str_to_uint(s, 10, &port32)) {
        if (port32 < ofp_to_u16(OFPP_MAX)) {
            /* Pass. */
        } else if (port32 < ofp_to_u16(OFPP_FIRST_RESV)) {
            VLOG_WARN("port %u is a reserved OF1.0 port number that will "
                      "be translated to %u when talking to an OF1.1 or "
                      "later controller", port32, port32 + OFPP11_OFFSET);
        } else if (port32 <= ofp_to_u16(OFPP_LAST_RESV)) {
            char name[OFP_MAX_PORT_NAME_LEN];

            ofputil_port_to_string(u16_to_ofp(port32), name, sizeof name);
            VLOG_WARN_ONCE("referring to port %s as %"PRIu32" is deprecated "
                           "for compatibility with OpenFlow 1.1 and later",
                           name, port32);
        } else if (port32 < ofp11_to_u32(OFPP11_MAX)) {
            VLOG_WARN("port %u is outside the supported range 0 through "
                      "%"PRIx16" or 0x%x through 0x%"PRIx32, port32,
                      UINT16_MAX, ofp11_to_u32(OFPP11_MAX), UINT32_MAX);
            return false;
        } else {
            port32 -= OFPP11_OFFSET;
        }

        *portp = u16_to_ofp(port32);
        return true;
    } else {
        struct pair {
            const char *name;
            ofp_port_t value;
        };
        static const struct pair pairs[] = {
#define OFPUTIL_NAMED_PORT(NAME) {#NAME, OFPP_##NAME},
            OFPUTIL_NAMED_PORTS_WITH_NONE
#undef OFPUTIL_NAMED_PORT
        };
        const struct pair *p;

        for (p = pairs; p < &pairs[ARRAY_SIZE(pairs)]; p++) {
            if (!strcasecmp(s, p->name)) {
                *portp = p->value;
                return true;
            }
        }
        return false;
    }
}