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

ofputil_port_stats_from_ofp10(struct ofputil_port_stats *ops,
                              const struct ofp10_port_stats *ps10)
{

    ops->port_no = u16_to_ofp(ntohs(ps10->port_no));
    ops->stats.rx_packets = ntohll(get_32aligned_be64(&ps10->rx_packets));
    ops->stats.tx_packets = ntohll(get_32aligned_be64(&ps10->tx_packets));
    ops->stats.rx_bytes = ntohll(get_32aligned_be64(&ps10->rx_bytes));
    ops->stats.tx_bytes = ntohll(get_32aligned_be64(&ps10->tx_bytes));
    ops->stats.rx_dropped = ntohll(get_32aligned_be64(&ps10->rx_dropped));
    ops->stats.tx_dropped = ntohll(get_32aligned_be64(&ps10->tx_dropped));
    ops->stats.rx_errors = ntohll(get_32aligned_be64(&ps10->rx_errors));
    ops->stats.tx_errors = ntohll(get_32aligned_be64(&ps10->tx_errors));
    ops->stats.rx_frame_errors =
        ntohll(get_32aligned_be64(&ps10->rx_frame_err));
    ops->stats.rx_over_errors = ntohll(get_32aligned_be64(&ps10->rx_over_err));
    ops->stats.rx_crc_errors = ntohll(get_32aligned_be64(&ps10->rx_crc_err));
    ops->stats.collisions = ntohll(get_32aligned_be64(&ps10->collisions));
    ops->duration_sec = ops->duration_nsec = UINT32_MAX;

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_port_stats_from_ofp11(struct ofputil_port_stats *ops,
                              const struct ofp11_port_stats *ps11)
{
    enum ofperr error;

    error = ofputil_port_from_ofp11(ps11->port_no, &ops->port_no);
    if (error) {
        return error;
    }

    ops->stats.rx_packets = ntohll(ps11->rx_packets);
    ops->stats.tx_packets = ntohll(ps11->tx_packets);
    ops->stats.rx_bytes = ntohll(ps11->rx_bytes);
    ops->stats.tx_bytes = ntohll(ps11->tx_bytes);
    ops->stats.rx_dropped = ntohll(ps11->rx_dropped);
    ops->stats.tx_dropped = ntohll(ps11->tx_dropped);
    ops->stats.rx_errors = ntohll(ps11->rx_errors);
    ops->stats.tx_errors = ntohll(ps11->tx_errors);
    ops->stats.rx_frame_errors = ntohll(ps11->rx_frame_err);
    ops->stats.rx_over_errors = ntohll(ps11->rx_over_err);
    ops->stats.rx_crc_errors = ntohll(ps11->rx_crc_err);
    ops->stats.collisions = ntohll(ps11->collisions);
    ops->duration_sec = ops->duration_nsec = UINT32_MAX;

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_port_stats_from_ofp13(struct ofputil_port_stats *ops,
                              const struct ofp13_port_stats *ps13)
{
    enum ofperr error = ofputil_port_stats_from_ofp11(ops, &ps13->ps);
    if (!error) {
        ops->duration_sec = ntohl(ps13->duration_sec);
        ops->duration_nsec = ntohl(ps13->duration_nsec);
    }
    return error;
}

Project: ovs
File: ofp-util.c

ofputil_port_stats_to_ofp10(const struct ofputil_port_stats *ops,
                            struct ofp10_port_stats *ps10)
{
    ps10->port_no = htons(ofp_to_u16(ops->port_no));
    memset(ps10->pad, 0, sizeof ps10->pad);
    put_32aligned_be64(&ps10->rx_packets, htonll(ops->stats.rx_packets));
    put_32aligned_be64(&ps10->tx_packets, htonll(ops->stats.tx_packets));
    put_32aligned_be64(&ps10->rx_bytes, htonll(ops->stats.rx_bytes));
    put_32aligned_be64(&ps10->tx_bytes, htonll(ops->stats.tx_bytes));
    put_32aligned_be64(&ps10->rx_dropped, htonll(ops->stats.rx_dropped));
    put_32aligned_be64(&ps10->tx_dropped, htonll(ops->stats.tx_dropped));
    put_32aligned_be64(&ps10->rx_errors, htonll(ops->stats.rx_errors));
    put_32aligned_be64(&ps10->tx_errors, htonll(ops->stats.tx_errors));
    put_32aligned_be64(&ps10->rx_frame_err, htonll(ops->stats.rx_frame_errors));
    put_32aligned_be64(&ps10->rx_over_err, htonll(ops->stats.rx_over_errors));
    put_32aligned_be64(&ps10->rx_crc_err, htonll(ops->stats.rx_crc_errors));
    put_32aligned_be64(&ps10->collisions, htonll(ops->stats.collisions));
}

Project: ovs
File: ofp-util.c

ofputil_port_stats_to_ofp11(const struct ofputil_port_stats *ops,
                            struct ofp11_port_stats *ps11)
{
    ps11->port_no = ofputil_port_to_ofp11(ops->port_no);
    memset(ps11->pad, 0, sizeof ps11->pad);
    ps11->rx_packets = htonll(ops->stats.rx_packets);
    ps11->tx_packets = htonll(ops->stats.tx_packets);
    ps11->rx_bytes = htonll(ops->stats.rx_bytes);
    ps11->tx_bytes = htonll(ops->stats.tx_bytes);
    ps11->rx_dropped = htonll(ops->stats.rx_dropped);
    ps11->tx_dropped = htonll(ops->stats.tx_dropped);
    ps11->rx_errors = htonll(ops->stats.rx_errors);
    ps11->tx_errors = htonll(ops->stats.tx_errors);
    ps11->rx_frame_err = htonll(ops->stats.rx_frame_errors);
    ps11->rx_over_err = htonll(ops->stats.rx_over_errors);
    ps11->rx_crc_err = htonll(ops->stats.rx_crc_errors);
    ps11->collisions = htonll(ops->stats.collisions);
}

Project: ovs
File: ofp-util.c

ofputil_port_stats_to_ofp13(const struct ofputil_port_stats *ops,
                            struct ofp13_port_stats *ps13)
{
    ofputil_port_stats_to_ofp11(ops, &ps13->ps);
    ps13->duration_sec = htonl(ops->duration_sec);
    ps13->duration_nsec = htonl(ops->duration_nsec);
}

Project: ovs
File: ofp-util.c

ofputil_port_to_string(ofp_port_t port,
                       char namebuf[OFP_MAX_PORT_NAME_LEN], size_t bufsize)
{
    switch (port) {
#define OFPUTIL_NAMED_PORT(NAME)                        \
        case OFPP_##NAME:                               \
            ovs_strlcpy(namebuf, #NAME, bufsize);       \
            break;
        OFPUTIL_NAMED_PORTS
#undef OFPUTIL_NAMED_PORT

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

Project: ovs
File: ofp-util.c

ofputil_protocol_from_ofp_version(enum ofp_version version)
{
    return rightmost_1bit(ofputil_protocols_from_ofp_version(version));
}

Project: ovs
File: ofp-util.c

ofputil_protocol_from_string__(const char *s, size_t n)
{
    const struct proto_abbrev *p;
    int i;

    for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) {
        enum ofputil_protocol bit = 1u << i;
        const char *name = ofputil_protocol_to_string(bit);

        if (name && n == strlen(name) && !strncasecmp(s, name, n)) {
            return bit;
        }
    }

    for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
        if (n == strlen(p->name) && !strncasecmp(s, p->name, n)) {
            return p->protocol;
        }
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_protocol_is_valid(enum ofputil_protocol protocol)
{
    return protocol & OFPUTIL_P_ANY && is_pow2(protocol);
}

Project: ovs
File: ofp-util.c

ofputil_protocol_set_base(enum ofputil_protocol cur,
                          enum ofputil_protocol new_base)
{
    bool tid = (cur & OFPUTIL_P_TID) != 0;

    switch (new_base) {
    case OFPUTIL_P_OF10_STD:
    case OFPUTIL_P_OF10_STD_TID:
        return ofputil_protocol_set_tid(OFPUTIL_P_OF10_STD, tid);

    case OFPUTIL_P_OF10_NXM:
    case OFPUTIL_P_OF10_NXM_TID:
        return ofputil_protocol_set_tid(OFPUTIL_P_OF10_NXM, tid);

    case OFPUTIL_P_OF11_STD:
        return ofputil_protocol_set_tid(OFPUTIL_P_OF11_STD, tid);

    case OFPUTIL_P_OF12_OXM:
        return ofputil_protocol_set_tid(OFPUTIL_P_OF12_OXM, tid);

    case OFPUTIL_P_OF13_OXM:
        return ofputil_protocol_set_tid(OFPUTIL_P_OF13_OXM, tid);

    case OFPUTIL_P_OF14_OXM:
        return ofputil_protocol_set_tid(OFPUTIL_P_OF14_OXM, tid);

    case OFPUTIL_P_OF15_OXM:
        return ofputil_protocol_set_tid(OFPUTIL_P_OF15_OXM, tid);

    case OFPUTIL_P_OF16_OXM:
        return ofputil_protocol_set_tid(OFPUTIL_P_OF16_OXM, tid);

    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_protocol_set_tid(enum ofputil_protocol protocol, bool enable)
{
    switch (protocol) {
    case OFPUTIL_P_OF10_STD:
    case OFPUTIL_P_OF10_STD_TID:
        return enable ? OFPUTIL_P_OF10_STD_TID : OFPUTIL_P_OF10_STD;

    case OFPUTIL_P_OF10_NXM:
    case OFPUTIL_P_OF10_NXM_TID:
        return enable ? OFPUTIL_P_OF10_NXM_TID : OFPUTIL_P_OF10_NXM;

    case OFPUTIL_P_OF11_STD:
        return OFPUTIL_P_OF11_STD;

    case OFPUTIL_P_OF12_OXM:
        return OFPUTIL_P_OF12_OXM;

    case OFPUTIL_P_OF13_OXM:
        return OFPUTIL_P_OF13_OXM;

    case OFPUTIL_P_OF14_OXM:
        return OFPUTIL_P_OF14_OXM;

    case OFPUTIL_P_OF15_OXM:
        return OFPUTIL_P_OF15_OXM;

    case OFPUTIL_P_OF16_OXM:
        return OFPUTIL_P_OF16_OXM;

    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_protocol_to_base(enum ofputil_protocol protocol)
{
    return ofputil_protocol_set_tid(protocol, false);
}

Project: ovs
File: ofp-util.c

ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol)
{
    switch (protocol) {
    case OFPUTIL_P_OF10_STD:
    case OFPUTIL_P_OF10_STD_TID:
    case OFPUTIL_P_OF10_NXM:
    case OFPUTIL_P_OF10_NXM_TID:
        return OFP10_VERSION;
    case OFPUTIL_P_OF11_STD:
        return OFP11_VERSION;
    case OFPUTIL_P_OF12_OXM:
        return OFP12_VERSION;
    case OFPUTIL_P_OF13_OXM:
        return OFP13_VERSION;
    case OFPUTIL_P_OF14_OXM:
        return OFP14_VERSION;
    case OFPUTIL_P_OF15_OXM:
        return OFP15_VERSION;
    case OFPUTIL_P_OF16_OXM:
        return OFP16_VERSION;
    }

    OVS_NOT_REACHED();
}

Project: ovs
File: ofp-util.c

ofputil_protocols_from_ofp_version(enum ofp_version version)
{
    switch (version) {
    case OFP10_VERSION:
        return OFPUTIL_P_OF10_STD_ANY | OFPUTIL_P_OF10_NXM_ANY;
    case OFP11_VERSION:
        return OFPUTIL_P_OF11_STD;
    case OFP12_VERSION:
        return OFPUTIL_P_OF12_OXM;
    case OFP13_VERSION:
        return OFPUTIL_P_OF13_OXM;
    case OFP14_VERSION:
        return OFPUTIL_P_OF14_OXM;
    case OFP15_VERSION:
        return OFPUTIL_P_OF15_OXM;
    case OFP16_VERSION:
        return OFPUTIL_P_OF16_OXM;
    default:
        return 0;
    }
}

Project: ovs
File: ofp-util.c

ofputil_protocols_from_string(const char *s)
{
    const char *orig_s = s;
    enum ofputil_protocol protocols;

    protocols = 0;
    while (*s) {
        enum ofputil_protocol p;
        size_t n;

        n = strcspn(s, ",");
        if (n == 0) {
            s++;
            continue;
        }

        p = ofputil_protocol_from_string__(s, n);
        if (!p) {
            ovs_fatal(0, "%.*s: unknown flow protocol", (int) n, s);
        }
        protocols |= p;

        s += n;
    }

    if (!protocols) {
        ovs_fatal(0, "%s: no flow protocol specified", orig_s);
    }
    return protocols;
}

Project: ovs
File: ofp-util.c

ofputil_protocols_from_version_bitmap(uint32_t bitmap)
{
    enum ofputil_protocol protocols = 0;

    for (; bitmap; bitmap = zero_rightmost_1bit(bitmap)) {
        enum ofp_version version = rightmost_1bit_idx(bitmap);

        protocols |= ofputil_protocols_from_ofp_version(version);
    }

    return protocols;
}

Project: ovs
File: ofp-util.c

ofputil_protocols_to_string(enum ofputil_protocol protocols)
{
    struct ds s;

    ovs_assert(!(protocols & ~OFPUTIL_P_ANY));
    if (protocols == 0) {
        return xstrdup("none");
    }

    ds_init(&s);
    while (protocols) {
        const struct proto_abbrev *p;
        int i;

        if (s.length) {
            ds_put_char(&s, ',');
        }

        for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
            if ((protocols & p->protocol) == p->protocol) {
                ds_put_cstr(&s, p->name);
                protocols &= ~p->protocol;
                goto match;
            }
        }

        for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) {
            enum ofputil_protocol bit = 1u << i;

            if (protocols & bit) {
                ds_put_cstr(&s, ofputil_protocol_to_string(bit));
                protocols &= ~bit;
                goto match;
            }
        }
        OVS_NOT_REACHED();

    match: ;
    }
    return ds_steal_cstr(&s);
}

Project: ovs
File: ofp-util.c

ofputil_protocols_to_version_bitmap(enum ofputil_protocol protocols)
{
    uint32_t bitmap = 0;

    for (; protocols; protocols = zero_rightmost_1bit(protocols)) {
        enum ofputil_protocol protocol = rightmost_1bit(protocols);

        bitmap |= 1u << ofputil_protocol_to_ofp_version(protocol);
    }

    return bitmap;
}

Project: ovs
File: ofp-util.c

ofputil_pull_band_stats(struct ofpbuf *msg, size_t len, uint16_t *n_bands,
                        struct ofpbuf *bands)
{
    const struct ofp13_meter_band_stats *ombs;
    struct ofputil_meter_band_stats *mbs;
    uint16_t n, i;

    ombs = ofpbuf_try_pull(msg, len);
    if (!ombs) {
        return OFPERR_OFPBRC_BAD_LEN;
    }

    n = len / sizeof *ombs;
    if (len != n * sizeof *ombs) {
        return OFPERR_OFPBRC_BAD_LEN;
    }

    mbs = ofpbuf_put_uninit(bands, len);

    for (i = 0; i < n; ++i) {
        mbs[i].packet_count = ntohll(ombs[i].packet_band_count);
        mbs[i].byte_count = ntohll(ombs[i].byte_band_count);
    }
    *n_bands = n;
    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_pull_bands(struct ofpbuf *msg, size_t len, uint16_t *n_bands,
                   struct ofpbuf *bands)
{
    const struct ofp13_meter_band_header *ombh;
    struct ofputil_meter_band *mb;
    uint16_t n = 0;

    ombh = ofpbuf_try_pull(msg, len);
    if (!ombh) {
        return OFPERR_OFPBRC_BAD_LEN;
    }

    while (len >= sizeof (struct ofp13_meter_band_drop)) {
        size_t ombh_len = ntohs(ombh->len);
        /* All supported band types have the same length. */
        if (ombh_len != sizeof (struct ofp13_meter_band_drop)) {
            return OFPERR_OFPBRC_BAD_LEN;
        }
        mb = ofpbuf_put_uninit(bands, sizeof *mb);
        mb->type = ntohs(ombh->type);
        if (mb->type != OFPMBT13_DROP && mb->type != OFPMBT13_DSCP_REMARK) {
            return OFPERR_OFPMMFC_BAD_BAND;
        }
        mb->rate = ntohl(ombh->rate);
        mb->burst_size = ntohl(ombh->burst_size);
        mb->prec_level = (mb->type == OFPMBT13_DSCP_REMARK) ?
            ((struct ofp13_meter_band_dscp_remark *)ombh)->prec_level : 0;
        n++;
        len -= ombh_len;
        ombh = ALIGNED_CAST(struct ofp13_meter_band_header *,
                            (char *) ombh + ombh_len);
    }
    if (len) {
        return OFPERR_OFPBRC_BAD_LEN;
    }
    *n_bands = n;
    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_pull_ipfix_stats(struct ofputil_ipfix_stats *is, struct ofpbuf *msg)
{
    enum ofperr error;
    enum ofpraw raw;

    memset(is, 0xFF, sizeof (*is));

    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_NXST_IPFIX_BRIDGE_REPLY ||
               raw == OFPRAW_NXST_IPFIX_FLOW_REPLY) {
        struct nx_ipfix_stats_reply *reply;

        reply = ofpbuf_try_pull(msg, sizeof *reply);
        return ofputil_ipfix_stats_from_nx(is, reply);
    } else {
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_pull_ofp11_buckets(struct ofpbuf *msg, size_t buckets_length,
                           enum ofp_version version, struct ovs_list *buckets)
{
    struct ofp11_bucket *ob;
    uint32_t bucket_id = 0;

    ovs_list_init(buckets);
    while (buckets_length > 0) {
        struct ofputil_bucket *bucket;
        struct ofpbuf ofpacts;
        enum ofperr error;
        size_t ob_len;

        ob = (buckets_length >= sizeof *ob
              ? ofpbuf_try_pull(msg, sizeof *ob)
              : NULL);
        if (!ob) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "buckets end with %"PRIuSIZE" leftover bytes",
                         buckets_length);
            ofputil_bucket_list_destroy(buckets);
            return OFPERR_OFPGMFC_BAD_BUCKET;
        }

        ob_len = ntohs(ob->len);
        if (ob_len < sizeof *ob) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length "
                         "%"PRIuSIZE" is not valid", ob_len);
            ofputil_bucket_list_destroy(buckets);
            return OFPERR_OFPGMFC_BAD_BUCKET;
        } else if (ob_len > buckets_length) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length "
                         "%"PRIuSIZE" exceeds remaining buckets data size %"PRIuSIZE,
                         ob_len, buckets_length);
            ofputil_bucket_list_destroy(buckets);
            return OFPERR_OFPGMFC_BAD_BUCKET;
        }
        buckets_length -= ob_len;

        ofpbuf_init(&ofpacts, 0);
        error = ofpacts_pull_openflow_actions(msg, ob_len - sizeof *ob,
                                              version, NULL, NULL, &ofpacts);
        if (error) {
            ofpbuf_uninit(&ofpacts);
            ofputil_bucket_list_destroy(buckets);
            return error;
        }

        bucket = xzalloc(sizeof *bucket);
        bucket->weight = ntohs(ob->weight);
        error = ofputil_port_from_ofp11(ob->watch_port, &bucket->watch_port);
        if (error) {
            ofpbuf_uninit(&ofpacts);
            ofputil_bucket_list_destroy(buckets);
            free(bucket);
            return OFPERR_OFPGMFC_BAD_WATCH;
        }
        bucket->watch_group = ntohl(ob->watch_group);
        bucket->bucket_id = bucket_id++;

        bucket->ofpacts = ofpbuf_steal_data(&ofpacts);
        bucket->ofpacts_len = ofpacts.size;
        ovs_list_push_back(buckets, &bucket->list_node);
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_pull_ofp11_match(struct ofpbuf *buf, const struct tun_table *tun_table,
                         const struct vl_mff_map *vl_mff_map,
                         struct match *match, uint16_t *padded_match_len)
{
    struct ofp11_match_header *omh = buf->data;
    uint16_t match_len;

    if (buf->size < sizeof *omh) {
        return OFPERR_OFPBMC_BAD_LEN;
    }

    match_len = ntohs(omh->length);

    switch (ntohs(omh->type)) {
    case OFPMT_STANDARD: {
        struct ofp11_match *om;

        if (match_len != sizeof *om || buf->size < sizeof *om) {
            return OFPERR_OFPBMC_BAD_LEN;
        }
        om = ofpbuf_pull(buf, sizeof *om);
        if (padded_match_len) {
            *padded_match_len = match_len;
        }
        return ofputil_match_from_ofp11_match(om, match);
    }

    case OFPMT_OXM:
        if (padded_match_len) {
            *padded_match_len = ROUND_UP(match_len, 8);
        }
        return oxm_pull_match(buf, tun_table, vl_mff_map, match);

    default:
        return OFPERR_OFPBMC_BAD_TYPE;
    }
}

Project: ovs
File: ofp-util.c

ofputil_pull_ofp14_port(struct ofputil_phy_port *pp, struct ofpbuf *msg)
{
    struct ofp14_port *op = ofpbuf_try_pull(msg, sizeof *op);
    if (!op) {
        return OFPERR_OFPBRC_BAD_LEN;
    }

    size_t len = ntohs(op->length);
    if (len < sizeof *op || len - sizeof *op > msg->size) {
        return OFPERR_OFPBRC_BAD_LEN;
    }
    len -= sizeof *op;

    enum ofperr 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;

    struct ofpbuf properties = ofpbuf_const_initializer(ofpbuf_pull(msg, len),
                                                        len);
    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 OFPPDPT14_ETHERNET:
            error = parse_ofp14_port_ethernet_property(&payload, pp);
            break;

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

        if (error) {
            return error;
        }
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_pull_ofp14_port_stats(struct ofputil_port_stats *ops,
                              struct ofpbuf *msg)
{
    const struct ofp14_port_stats *ps14 = ofpbuf_try_pull(msg, sizeof *ps14);
    if (!ps14) {
        return OFPERR_OFPBRC_BAD_LEN;
    }

    size_t len = ntohs(ps14->length);
    if (len < sizeof *ps14 || len - sizeof *ps14 > msg->size) {
        return OFPERR_OFPBRC_BAD_LEN;
    }
    len -= sizeof *ps14;

    enum ofperr error = ofputil_port_from_ofp11(ps14->port_no, &ops->port_no);
    if (error) {
        return error;
    }

    ops->duration_sec = ntohl(ps14->duration_sec);
    ops->duration_nsec = ntohl(ps14->duration_nsec);
    ops->stats.rx_packets = ntohll(ps14->rx_packets);
    ops->stats.tx_packets = ntohll(ps14->tx_packets);
    ops->stats.rx_bytes = ntohll(ps14->rx_bytes);
    ops->stats.tx_bytes = ntohll(ps14->tx_bytes);
    ops->stats.rx_dropped = ntohll(ps14->rx_dropped);
    ops->stats.tx_dropped = ntohll(ps14->tx_dropped);
    ops->stats.rx_errors = ntohll(ps14->rx_errors);
    ops->stats.tx_errors = ntohll(ps14->tx_errors);


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

        error = ofpprop_pull(&properties, &payload, &type);
        if (error) {
            return error;
        }
        switch (type) {
        case OFPPSPT14_ETHERNET:
            error = parse_ofp14_port_stats_ethernet_property(&payload, ops);
            break;
        case OFPPROP_EXP(INTEL_VENDOR_ID, INTEL_PORT_STATS_RFC2819):
            error = parse_intel_port_stats_property(&payload,
                                                    INTEL_PORT_STATS_RFC2819,
                                                    ops);
            break;
        default:
            error = OFPPROP_UNKNOWN(true, "port stats", type);
            break;
        }

        if (error) {
            return error;
        }
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_pull_ofp14_queue_stats(struct ofputil_queue_stats *oqs,
                               struct ofpbuf *msg)
{
    const struct ofp14_queue_stats *qs14;
    size_t len;

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

    len = ntohs(qs14->length);
    if (len < sizeof *qs14 || len - sizeof *qs14 > msg->size) {
        return OFPERR_OFPBRC_BAD_LEN;
    }
    ofpbuf_pull(msg, len - sizeof *qs14);

    /* No properties yet defined, so ignore them for now. */

    return ofputil_queue_stats_from_ofp13(oqs, &qs14->qs);
}

Project: ovs
File: ofp-util.c

ofputil_pull_ofp15_buckets(struct ofpbuf *msg, size_t buckets_length,
                           enum ofp_version version, uint8_t group_type,
                           struct ovs_list *buckets)
{
    struct ofp15_bucket *ob;

    ovs_list_init(buckets);
    while (buckets_length > 0) {
        struct ofputil_bucket *bucket = NULL;
        struct ofpbuf ofpacts;
        enum ofperr err = OFPERR_OFPGMFC_BAD_BUCKET;
        size_t ob_len, actions_len, properties_len;
        ovs_be32 watch_port = ofputil_port_to_ofp11(OFPP_ANY);
        ovs_be32 watch_group = htonl(OFPG_ANY);
        ovs_be16 weight = htons(group_type == OFPGT11_SELECT ? 1 : 0);

        ofpbuf_init(&ofpacts, 0);

        ob = ofpbuf_try_pull(msg, sizeof *ob);
        if (!ob) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "buckets end with %"PRIuSIZE
                         " leftover bytes", buckets_length);
            goto err;
        }

        ob_len = ntohs(ob->len);
        actions_len = ntohs(ob->action_array_len);

        if (ob_len < sizeof *ob) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length "
                         "%"PRIuSIZE" is not valid", ob_len);
            goto err;
        } else if (ob_len > buckets_length) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length "
                         "%"PRIuSIZE" exceeds remaining buckets data size %"
                         PRIuSIZE, ob_len, buckets_length);
            goto err;
        } else if (actions_len > ob_len - sizeof *ob) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket actions "
                         "length %"PRIuSIZE" exceeds remaining bucket "
                         "data size %"PRIuSIZE, actions_len,
                         ob_len - sizeof *ob);
            goto err;
        }
        buckets_length -= ob_len;

        err = ofpacts_pull_openflow_actions(msg, actions_len, version,
                                            NULL, NULL, &ofpacts);
        if (err) {
            goto err;
        }

        properties_len = ob_len - sizeof *ob - actions_len;
        struct ofpbuf properties = ofpbuf_const_initializer(
            ofpbuf_pull(msg, properties_len), properties_len);
        while (properties.size > 0) {
            struct ofpbuf payload;
            uint64_t type;

            err = ofpprop_pull(&properties, &payload, &type);
            if (err) {
                goto err;
            }

            switch (type) {
            case OFPGBPT15_WEIGHT:
                err = ofpprop_parse_be16(&payload, &weight);
                break;

            case OFPGBPT15_WATCH_PORT:
                err = ofpprop_parse_be32(&payload, &watch_port);
                break;

            case OFPGBPT15_WATCH_GROUP:
                err = ofpprop_parse_be32(&payload, &watch_group);
                break;

            default:
                err = OFPPROP_UNKNOWN(false, "group bucket", type);
                break;
            }

            if (err) {
                goto err;
            }
        }

        bucket = xzalloc(sizeof *bucket);

        bucket->weight = ntohs(weight);
        err = ofputil_port_from_ofp11(watch_port, &bucket->watch_port);
        if (err) {
            err = OFPERR_OFPGMFC_BAD_WATCH;
            goto err;
        }
        bucket->watch_group = ntohl(watch_group);
        bucket->bucket_id = ntohl(ob->bucket_id);
        if (bucket->bucket_id > OFPG15_BUCKET_MAX) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "bucket id (%u) is out of range",
                         bucket->bucket_id);
            err = OFPERR_OFPGMFC_BAD_BUCKET;
            goto err;
        }

        bucket->ofpacts = ofpbuf_steal_data(&ofpacts);
        bucket->ofpacts_len = ofpacts.size;
        ovs_list_push_back(buckets, &bucket->list_node);

        continue;

    err:
        free(bucket);
        ofpbuf_uninit(&ofpacts);
        ofputil_bucket_list_destroy(buckets);
        return err;
    }

    if (ofputil_bucket_check_duplicate_id(buckets)) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "Duplicate bucket id");
        ofputil_bucket_list_destroy(buckets);
        return OFPERR_OFPGMFC_BAD_BUCKET;
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_pull_ofp15_group_mod(struct ofpbuf *msg, enum ofp_version ofp_version,
                             struct ofputil_group_mod *gm)
{
    const struct ofp15_group_mod *ogm;
    uint16_t bucket_list_len;
    enum ofperr error = OFPERR_OFPGMFC_BAD_BUCKET;

    ogm = ofpbuf_pull(msg, sizeof *ogm);
    gm->command = ntohs(ogm->command);
    gm->type = ogm->type;
    gm->group_id = ntohl(ogm->group_id);

    gm->command_bucket_id = ntohl(ogm->command_bucket_id);
    switch (gm->command) {
    case OFPGC15_REMOVE_BUCKET:
        if (gm->command_bucket_id == OFPG15_BUCKET_ALL) {
            error = 0;
        }
        /* Fall through */
    case OFPGC15_INSERT_BUCKET:
        if (gm->command_bucket_id <= OFPG15_BUCKET_MAX ||
            gm->command_bucket_id == OFPG15_BUCKET_FIRST
            || gm->command_bucket_id == OFPG15_BUCKET_LAST) {
            error = 0;
        }
        break;

    case OFPGC11_ADD:
    case OFPGC11_MODIFY:
    case OFPGC11_ADD_OR_MOD:
    case OFPGC11_DELETE:
    default:
        if (gm->command_bucket_id == OFPG15_BUCKET_ALL) {
            error = 0;
        }
        break;
    }
    if (error) {
        VLOG_WARN_RL(&bad_ofmsg_rl,
                     "group command bucket id (%u) is out of range",
                     gm->command_bucket_id);
        return OFPERR_OFPGMFC_BAD_BUCKET;
    }

    bucket_list_len = ntohs(ogm->bucket_array_len);
    if (bucket_list_len > msg->size) {
        return OFPERR_OFPBRC_BAD_LEN;
    }
    error = ofputil_pull_ofp15_buckets(msg, bucket_list_len, ofp_version,
                                       gm->type, &gm->buckets);
    if (error) {
        return error;
    }

    error = parse_ofp15_group_properties(msg, gm->type, gm->command,
                                         &gm->props, msg->size);
    if (error) {
        ofputil_bucket_list_destroy(&gm->buckets);
    }
    return error;
}

Project: ovs
File: ofp-util.c

ofputil_pull_phy_port(enum ofp_version ofp_version, struct ofpbuf *b,
                      struct ofputil_phy_port *pp)
{
    memset(pp, 0, sizeof *pp);

    switch (ofp_version) {
    case OFP10_VERSION: {
        const struct ofp10_phy_port *opp = ofpbuf_try_pull(b, sizeof *opp);
        return opp ? ofputil_decode_ofp10_phy_port(pp, opp) : EOF;
    }
    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION: {
        const struct ofp11_port *op = ofpbuf_try_pull(b, sizeof *op);
        return op ? ofputil_decode_ofp11_port(pp, op) : EOF;
    }
    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION:
        return b->size ? ofputil_pull_ofp14_port(pp, b) : EOF;
    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_pull_queue_get_config_reply(struct ofpbuf *msg,
                                    struct ofputil_queue_config *queue)
{
    enum ofpraw raw;
    if (!msg->header) {
        /* Pull OpenFlow header. */
        raw = ofpraw_pull_assert(msg);

        /* Pull protocol-specific ofp_queue_get_config_reply header (OF1.4
         * doesn't have one at all). */
        if (raw == OFPRAW_OFPT10_QUEUE_GET_CONFIG_REPLY) {
            ofpbuf_pull(msg, sizeof(struct ofp10_queue_get_config_reply));
        } else if (raw == OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY) {
            ofpbuf_pull(msg, sizeof(struct ofp11_queue_get_config_reply));
        } else {
            ovs_assert(raw == OFPRAW_OFPST14_QUEUE_DESC_REPLY);
        }
    } else {
        raw = ofpraw_decode_assert(msg->header);
    }

    queue->min_rate = UINT16_MAX;
    queue->max_rate = UINT16_MAX;

    if (!msg->size) {
        return EOF;
    } else if (raw == OFPRAW_OFPST14_QUEUE_DESC_REPLY) {
        return ofputil_pull_queue_get_config_reply14(msg, queue);
    } else {
        return ofputil_pull_queue_get_config_reply10(msg, queue);
    }
}

Project: ovs
File: ofp-util.c

ofputil_pull_queue_get_config_reply10(struct ofpbuf *msg,
                                      struct ofputil_queue_config *queue)
{
    const struct ofp_header *oh = msg->header;
    unsigned int opq_len;       /* Length of protocol-specific queue header. */
    unsigned int len;           /* Total length of queue + properties. */

    /* Obtain the port number from the message header. */
    if (oh->version == OFP10_VERSION) {
        const struct ofp10_queue_get_config_reply *oqgcr10 = msg->msg;
        queue->port = u16_to_ofp(ntohs(oqgcr10->port));
    } else {
        const struct ofp11_queue_get_config_reply *oqgcr11 = msg->msg;
        enum ofperr error = ofputil_port_from_ofp11(oqgcr11->port,
                                                    &queue->port);
        if (error) {
            return error;
        }
    }

    /* Pull off the queue header and get the queue number and length. */
    if (oh->version < OFP12_VERSION) {
        const struct ofp10_packet_queue *opq10;
        opq10 = ofpbuf_try_pull(msg, sizeof *opq10);
        if (!opq10) {
            return OFPERR_OFPBRC_BAD_LEN;
        }
        queue->queue = ntohl(opq10->queue_id);
        len = ntohs(opq10->len);
        opq_len = sizeof *opq10;
    } else {
        const struct ofp12_packet_queue *opq12;
        opq12 = ofpbuf_try_pull(msg, sizeof *opq12);
        if (!opq12) {
            return OFPERR_OFPBRC_BAD_LEN;
        }
        queue->queue = ntohl(opq12->queue_id);
        len = ntohs(opq12->len);
        opq_len = sizeof *opq12;
    }

    /* Length check. */
    if (len < opq_len || len > msg->size + opq_len || len % 8) {
        return OFPERR_OFPBRC_BAD_LEN;
    }
    len -= opq_len;

    /* Pull properties.  The format of these properties differs from used in
     * OF1.4+ so we can't use the common property functions. */
    while (len > 0) {
        const struct ofp10_queue_prop_header *hdr;
        unsigned int property;
        unsigned int prop_len;
        enum ofperr error = 0;

        hdr = ofpbuf_at_assert(msg, 0, sizeof *hdr);
        prop_len = ntohs(hdr->len);
        if (prop_len < sizeof *hdr || prop_len > len || prop_len % 8) {
            return OFPERR_OFPBRC_BAD_LEN;
        }

        property = ntohs(hdr->property);
        switch (property) {
        case OFPQT10_MIN_RATE:
            error = parse_ofp10_queue_rate(hdr, &queue->min_rate);
            break;

        case OFPQT11_MAX_RATE:
            error = parse_ofp10_queue_rate(hdr, &queue->max_rate);
            break;

        default:
            VLOG_INFO_RL(&bad_ofmsg_rl, "unknown queue property %u", property);
            break;
        }
        if (error) {
            return error;
        }

        ofpbuf_pull(msg, prop_len);
        len -= prop_len;
    }
    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_pull_queue_get_config_reply14(struct ofpbuf *msg,
                                      struct ofputil_queue_config *queue)
{
    struct ofp14_queue_desc *oqd14 = ofpbuf_try_pull(msg, sizeof *oqd14);
    if (!oqd14) {
        return OFPERR_OFPBRC_BAD_LEN;
    }
    enum ofperr error = ofputil_port_from_ofp11(oqd14->port_no, &queue->port);
    if (error) {
        return error;
    }
    queue->queue = ntohl(oqd14->queue_id);

    /* Length check. */
    unsigned int len = ntohs(oqd14->len);
    if (len < sizeof *oqd14 || len > msg->size + sizeof *oqd14 || len % 8) {
        return OFPERR_OFPBRC_BAD_LEN;
    }
    len -= sizeof *oqd14;

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

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

        switch (type) {
        case OFPQDPT14_MIN_RATE:
            error = ofpprop_parse_u16(&payload, &queue->min_rate);
            break;

        case OFPQDPT14_MAX_RATE:
            error = ofpprop_parse_u16(&payload, &queue->max_rate);
            break;

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

        if (error) {
            return error;
        }
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_pull_switch_features(struct ofpbuf *b,
                             struct ofputil_switch_features *features)
{
    const struct ofp_header *oh = b->data;
    enum ofpraw raw = ofpraw_pull_assert(b);
    const struct ofp_switch_features *osf = ofpbuf_pull(b, sizeof *osf);
    features->datapath_id = ntohll(osf->datapath_id);
    features->n_buffers = ntohl(osf->n_buffers);
    features->n_tables = osf->n_tables;
    features->auxiliary_id = 0;

    features->capabilities = ntohl(osf->capabilities) &
        ofputil_capabilities_mask(oh->version);

    if (raw == OFPRAW_OFPT10_FEATURES_REPLY) {
        if (osf->capabilities & htonl(OFPC10_STP)) {
            features->capabilities |= OFPUTIL_C_STP;
        }
        features->ofpacts = ofpact_bitmap_from_openflow(osf->actions,
                                                        OFP10_VERSION);
    } else if (raw == OFPRAW_OFPT11_FEATURES_REPLY
               || raw == OFPRAW_OFPT13_FEATURES_REPLY) {
        if (osf->capabilities & htonl(OFPC11_GROUP_STATS)) {
            features->capabilities |= OFPUTIL_C_GROUP_STATS;
        }
        features->ofpacts = 0;
        if (raw == OFPRAW_OFPT13_FEATURES_REPLY) {
            features->auxiliary_id = osf->auxiliary_id;
        }
    } else {
        return OFPERR_OFPBRC_BAD_VERSION;
    }

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_put_async_config__(const struct ofputil_async_cfg *ac,
                           struct ofpbuf *buf, bool tlv,
                           enum ofp_version version, uint32_t oams)
{
    if (!tlv) {
        struct nx_async_config *msg = ofpbuf_put_zeros(buf, sizeof *msg);
        encode_legacy_async_masks(ac, OAM_PACKET_IN, version,
                                  msg->packet_in_mask);
        encode_legacy_async_masks(ac, OAM_PORT_STATUS, version,
                                  msg->port_status_mask);
        encode_legacy_async_masks(ac, OAM_FLOW_REMOVED, version,
                                  msg->flow_removed_mask);
    } else {
        FOR_EACH_ASYNC_PROP (ap) {
            if (oams & (1u << ap->oam)) {
                size_t ofs = buf->size;
                ofpprop_put_be32(buf, ap->prop_type,
                                 encode_async_mask(ac, ap, version));

                /* For experimenter properties, we need to use type 0xfffe for
                 * master and 0xffff for slaves. */
                if (ofpprop_is_experimenter(ap->prop_type)) {
                    struct ofp_prop_experimenter *ope
                        = ofpbuf_at_assert(buf, ofs, sizeof *ope);
                    ope->type = ap->master ? htons(0xffff) : htons(0xfffe);
                }
            }
        }
    }
}

Project: ovs
File: ofp-util.c

ofputil_put_group_prop_ntr_selection_method(enum ofp_version ofp_version,
                                            const struct ofputil_group_props *gp,
                                            struct ofpbuf *openflow)
{
    struct ntr_group_prop_selection_method *prop;
    size_t start;

    start = openflow->size;
    ofpbuf_put_zeros(openflow, sizeof *prop);
    oxm_put_field_array(openflow, &gp->fields, ofp_version);
    prop = ofpbuf_at_assert(openflow, start, sizeof *prop);
    prop->type = htons(OFPGPT15_EXPERIMENTER);
    prop->experimenter = htonl(NTR_VENDOR_ID);
    prop->exp_type = htonl(NTRT_SELECTION_METHOD);
    strcpy(prop->selection_method, gp->selection_method);
    prop->selection_method_param = htonll(gp->selection_method_param);
    ofpprop_end(openflow, start);
}

Project: ovs
File: ofp-util.c

ofputil_put_ofp10_table_stats(const struct ofputil_table_stats *stats,
                              const struct ofputil_table_features *features,
                              struct ofpbuf *buf)
{
    struct mf_bitmap wc = wild_or_nonmatchable_fields(features);
    struct ofp10_table_stats *out;

    out = ofpbuf_put_zeros(buf, sizeof *out);
    out->table_id = features->table_id;
    ovs_strlcpy(out->name, features->name, sizeof out->name);
    out->wildcards = mf_bitmap_to_of10(&wc);
    out->max_entries = htonl(features->max_entries);
    out->active_count = htonl(stats->active_count);
    put_32aligned_be64(&out->lookup_count, htonll(stats->lookup_count));
    put_32aligned_be64(&out->matched_count, htonll(stats->matched_count));
}

Project: ovs
File: ofp-util.c

ofputil_put_ofp11_match(struct ofpbuf *b, const struct match *match,
                        enum ofputil_protocol protocol)
{
    switch (protocol) {
    case OFPUTIL_P_OF10_STD:
    case OFPUTIL_P_OF10_STD_TID:
    case OFPUTIL_P_OF10_NXM:
    case OFPUTIL_P_OF10_NXM_TID:
        OVS_NOT_REACHED();

    case OFPUTIL_P_OF11_STD: {
        struct ofp11_match *om;

        /* Make sure that no padding is needed. */
        BUILD_ASSERT_DECL(sizeof *om % 8 == 0);

        om = ofpbuf_put_uninit(b, sizeof *om);
        ofputil_match_to_ofp11_match(match, om);
        return sizeof *om;
    }

    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 oxm_put_match(b, match,
                             ofputil_protocol_to_ofp_version(protocol));
    }

    OVS_NOT_REACHED();
}

Project: ovs
File: ofp-util.c

ofputil_put_ofp11_table_stats(const struct ofputil_table_stats *stats,
                              const struct ofputil_table_features *features,
                              struct ofpbuf *buf)
{
    struct mf_bitmap wc = wild_or_nonmatchable_fields(features);
    struct ofp11_table_stats *out;

    out = ofpbuf_put_zeros(buf, sizeof *out);
    out->table_id = features->table_id;
    ovs_strlcpy(out->name, features->name, sizeof out->name);
    out->wildcards = mf_bitmap_to_of11(&wc);
    out->match = mf_bitmap_to_of11(&features->match);
    out->instructions = ovsinst_bitmap_to_openflow(
        features->nonmiss.instructions, OFP11_VERSION);
    out->write_actions = ofpact_bitmap_to_openflow(
        features->nonmiss.write.ofpacts, OFP11_VERSION);
    out->apply_actions = ofpact_bitmap_to_openflow(
        features->nonmiss.apply.ofpacts, OFP11_VERSION);
    out->config = htonl(features->miss_config);
    out->max_entries = htonl(features->max_entries);
    out->active_count = htonl(stats->active_count);
    out->lookup_count = htonll(stats->lookup_count);
    out->matched_count = htonll(stats->matched_count);
}

Project: ovs
File: ofp-util.c

ofputil_put_ofp12_table_stats(const struct ofputil_table_stats *stats,
                              const struct ofputil_table_features *features,
                              struct ofpbuf *buf)
{
    struct ofp12_table_stats *out;

    out = ofpbuf_put_zeros(buf, sizeof *out);
    out->table_id = features->table_id;
    ovs_strlcpy(out->name, features->name, sizeof out->name);
    out->match = oxm_bitmap_from_mf_bitmap(&features->match, OFP12_VERSION);
    out->wildcards = oxm_bitmap_from_mf_bitmap(&features->wildcard,
                                             OFP12_VERSION);
    out->write_actions = ofpact_bitmap_to_openflow(
        features->nonmiss.write.ofpacts, OFP12_VERSION);
    out->apply_actions = ofpact_bitmap_to_openflow(
        features->nonmiss.apply.ofpacts, OFP12_VERSION);
    out->write_setfields = oxm_bitmap_from_mf_bitmap(
        &features->nonmiss.write.set_fields, OFP12_VERSION);
    out->apply_setfields = oxm_bitmap_from_mf_bitmap(
        &features->nonmiss.apply.set_fields, OFP12_VERSION);
    out->metadata_match = features->metadata_match;
    out->metadata_write = features->metadata_write;
    out->instructions = ovsinst_bitmap_to_openflow(
        features->nonmiss.instructions, OFP12_VERSION);
    out->config = ofputil_encode_table_config(features->miss_config,
                                              OFPUTIL_TABLE_EVICTION_DEFAULT,
                                              OFPUTIL_TABLE_VACANCY_DEFAULT,
                                              OFP12_VERSION);
    out->max_entries = htonl(features->max_entries);
    out->active_count = htonl(stats->active_count);
    out->lookup_count = htonll(stats->lookup_count);
    out->matched_count = htonll(stats->matched_count);
}

Project: ovs
File: ofp-util.c

ofputil_put_ofp13_table_stats(const struct ofputil_table_stats *stats,
                              struct ofpbuf *buf)
{
    struct ofp13_table_stats *out;

    out = ofpbuf_put_zeros(buf, sizeof *out);
    out->table_id = stats->table_id;
    out->active_count = htonl(stats->active_count);
    out->lookup_count = htonll(stats->lookup_count);
    out->matched_count = htonll(stats->matched_count);
}

Project: ovs
File: ofp-util.c

ofputil_put_ofp14_port(const struct ofputil_phy_port *pp,
                       struct ofpbuf *b)
{
    struct ofp14_port *op;
    struct ofp14_port_desc_prop_ethernet *eth;

    ofpbuf_prealloc_tailroom(b, sizeof *op + sizeof *eth);

    op = ofpbuf_put_zeros(b, sizeof *op);
    op->port_no = ofputil_port_to_ofp11(pp->port_no);
    op->length = htons(sizeof *op + sizeof *eth);
    op->hw_addr = pp->hw_addr;
    ovs_strlcpy(op->name, pp->name, sizeof op->name);
    op->config = htonl(pp->config & OFPPC11_ALL);
    op->state = htonl(pp->state & OFPPS11_ALL);

    eth = ofpprop_put_zeros(b, OFPPDPT14_ETHERNET, sizeof *eth);
    eth->curr = netdev_port_features_to_ofp11(pp->curr);
    eth->advertised = netdev_port_features_to_ofp11(pp->advertised);
    eth->supported = netdev_port_features_to_ofp11(pp->supported);
    eth->peer = netdev_port_features_to_ofp11(pp->peer);
    eth->curr_speed = htonl(pp->curr_speed);
    eth->max_speed = htonl(pp->max_speed);
}

Project: ovs
File: ofp-util.c

ofputil_put_ofp14_table_desc(const struct ofputil_table_desc *td,
                             struct ofpbuf *b, enum ofp_version version)
{
    struct ofp14_table_desc *otd;
    struct ofp14_table_mod_prop_vacancy *otv;
    size_t start_otd;

    start_otd = b->size;
    ofpbuf_put_zeros(b, sizeof *otd);

    ofpprop_put_u32(b, OFPTMPT14_EVICTION, td->eviction_flags);

    otv = ofpbuf_put_zeros(b, sizeof *otv);
    otv->type = htons(OFPTMPT14_VACANCY);
    otv->length = htons(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(b, start_otd, sizeof *otd);
    otd->length = htons(b->size - start_otd);
    otd->table_id = td->table_id;
    otd->config = ofputil_encode_table_config(OFPUTIL_TABLE_MISS_DEFAULT,
                                              td->eviction, td->vacancy,
                                              version);
}

Project: ovs
File: ofp-util.c

ofputil_put_ofp15_bucket(const struct ofputil_bucket *bucket,
                         uint32_t bucket_id, enum ofp11_group_type group_type,
                         struct ofpbuf *openflow, enum ofp_version ofp_version)
{
    struct ofp15_bucket *ob;
    size_t start, actions_start, actions_len;

    start = openflow->size;
    ofpbuf_put_zeros(openflow, sizeof *ob);

    actions_start = openflow->size;
    ofpacts_put_openflow_actions(bucket->ofpacts, bucket->ofpacts_len,
                                 openflow, ofp_version);
    actions_len = openflow->size - actions_start;

    if (group_type == OFPGT11_SELECT) {
        ofpprop_put_u16(openflow, OFPGBPT15_WEIGHT, bucket->weight);
    }
    if (bucket->watch_port != OFPP_ANY) {
        ofpprop_put_be32(openflow, OFPGBPT15_WATCH_PORT,
                         ofputil_port_to_ofp11(bucket->watch_port));
    }
    if (bucket->watch_group != OFPG_ANY) {
        ofpprop_put_u32(openflow, OFPGBPT15_WATCH_GROUP, bucket->watch_group);
    }

    ob = ofpbuf_at_assert(openflow, start, sizeof *ob);
    ob->len = htons(openflow->size - start);
    ob->action_array_len = htons(actions_len);
    ob->bucket_id = htonl(bucket_id);
}

Project: ovs
File: ofp-util.c

ofputil_put_packet_in(const struct ofputil_packet_in *pin,
                      enum ofp_version version, size_t include_bytes,
                      struct ofpbuf *msg)
{
    /* Add packet properties. */
    ofpprop_put(msg, NXPINT_PACKET, pin->packet, include_bytes);
    if (include_bytes != pin->packet_len) {
        ofpprop_put_u32(msg, NXPINT_FULL_LEN, pin->packet_len);
    }

    /* Add flow properties. */
    ofpprop_put_u8(msg, NXPINT_TABLE_ID, pin->table_id);
    if (pin->cookie != OVS_BE64_MAX) {
        ofpprop_put_be64(msg, NXPINT_COOKIE, pin->cookie);
    }

    /* Add other properties. */
    ofpprop_put_u8(msg, NXPINT_REASON,
                   encode_packet_in_reason(pin->reason, version));

    size_t start = ofpprop_start(msg, NXPINT_METADATA);
    oxm_put_raw(msg, &pin->flow_metadata, version);
    ofpprop_end(msg, start);
}

Project: ovs
File: ofp-util.c

ofputil_put_packet_in_private(const struct ofputil_packet_in_private *pin,
                              enum ofp_version version, size_t include_bytes,
                              struct ofpbuf *msg)
{
    ofputil_put_packet_in(&pin->public, version, include_bytes, msg);

    size_t continuation_ofs = ofpprop_start_nested(msg, NXPINT_CONTINUATION);
    size_t inner_ofs = msg->size;

    if (!uuid_is_zero(&pin->bridge)) {
        ofpprop_put_uuid(msg, NXCPT_BRIDGE, &pin->bridge);
    }

    struct ofpbuf pin_stack;
    ofpbuf_use_const(&pin_stack, pin->stack, pin->stack_size);

    while (pin_stack.size) {
        uint8_t len;
        uint8_t *val = nx_stack_pop(&pin_stack, &len);
        ofpprop_put(msg, NXCPT_STACK, val, len);
    }

    if (pin->mirrors) {
        ofpprop_put_u32(msg, NXCPT_MIRRORS, pin->mirrors);
    }

    if (pin->conntracked) {
        ofpprop_put_flag(msg, NXCPT_CONNTRACKED);
    }

    if (pin->actions_len) {
        /* Divide 'pin->actions' into groups that begins with an
         * unroll_xlate action.  For each group, emit a NXCPT_TABLE_ID and
         * NXCPT_COOKIE property (if either has changed; each is initially
         * assumed 0), then a NXCPT_ACTIONS property with the grouped
         * actions.
         *
         * The alternative is to make OFPACT_UNROLL_XLATE public.  We can
         * always do that later, since this is a private property. */
        const struct ofpact *const end = ofpact_end(pin->actions,
                                                    pin->actions_len);
        const struct ofpact_unroll_xlate *unroll = NULL;
        uint8_t table_id = 0;
        ovs_be64 cookie = 0;

        const struct ofpact *a;
        for (a = pin->actions; ; a = ofpact_next(a)) {
            if (a == end || a->type == OFPACT_UNROLL_XLATE) {
                if (unroll) {
                    if (table_id != unroll->rule_table_id) {
                        ofpprop_put_u8(msg, NXCPT_TABLE_ID,
                                       unroll->rule_table_id);
                        table_id = unroll->rule_table_id;
                    }
                    if (cookie != unroll->rule_cookie) {
                        ofpprop_put_be64(msg, NXCPT_COOKIE,
                                         unroll->rule_cookie);
                        cookie = unroll->rule_cookie;
                    }
                }

                const struct ofpact *start
                    = unroll ? ofpact_next(&unroll->ofpact) : pin->actions;
                put_actions_property(msg, NXCPT_ACTIONS, version,
                                     start, (a - start) * sizeof *a);

                if (a == end) {
                    break;
                }
                unroll = ofpact_get_UNROLL_XLATE(a);
            }
        }
    }

    if (pin->action_set_len) {
        size_t start = ofpprop_start_nested(msg, NXCPT_ACTION_SET);
        ofpacts_put_openflow_actions(pin->action_set,
                                     pin->action_set_len, msg, version);
        ofpprop_end(msg, start);
    }

    if (msg->size > inner_ofs) {
        ofpprop_end(msg, continuation_ofs);
    } else {
        msg->size = continuation_ofs;
    }
}

Project: ovs
File: ofp-util.c

ofputil_put_phy_port(enum ofp_version ofp_version,
                     const struct ofputil_phy_port *pp, struct ofpbuf *b)
{
    switch (ofp_version) {
    case OFP10_VERSION: {
        struct ofp10_phy_port *opp = ofpbuf_put_uninit(b, sizeof *opp);
        ofputil_encode_ofp10_phy_port(pp, opp);
        break;
    }

    case OFP11_VERSION:
    case OFP12_VERSION:
    case OFP13_VERSION: {
        struct ofp11_port *op = ofpbuf_put_uninit(b, sizeof *op);
        ofputil_encode_ofp11_port(pp, op);
        break;
    }

    case OFP14_VERSION:
    case OFP15_VERSION:
    case OFP16_VERSION:
        ofputil_put_ofp14_port(pp, b);
        break;

    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_put_switch_config(const struct ofputil_switch_config *config,
                          struct ofpbuf *b)
{
    const struct ofp_header *oh = b->data;
    struct ofp_switch_config *osc = ofpbuf_put_zeros(b, sizeof *osc);
    osc->flags = htons(config->frag);
    if (config->invalid_ttl_to_controller > 0 && oh->version < OFP13_VERSION) {
        osc->flags |= htons(OFPC_INVALID_TTL_TO_CONTROLLER);
    }
    osc->miss_send_len = htons(config->miss_send_len);
    return b;
}

Project: ovs
File: ofp-util.c

ofputil_put_switch_features_port(const struct ofputil_phy_port *pp,
                                 struct ofpbuf *b)
{
    const struct ofp_header *oh = b->data;

    if (oh->version < OFP13_VERSION) {
        /* Try adding a port description to the message, but drop it again if
         * the buffer overflows.  (This possibility for overflow is why
         * OpenFlow 1.3+ moved port descriptions into a multipart message.)  */
        size_t start_ofs = b->size;
        ofputil_put_phy_port(oh->version, pp, b);
        if (b->size > UINT16_MAX) {
            b->size = start_ofs;
        }
    }
}

Project: ovs
File: ofp-util.c

ofputil_queue_stats_from_ofp10(struct ofputil_queue_stats *oqs,
                               const struct ofp10_queue_stats *qs10)
{
    oqs->port_no = u16_to_ofp(ntohs(qs10->port_no));
    oqs->queue_id = ntohl(qs10->queue_id);
    oqs->tx_bytes = ntohll(get_32aligned_be64(&qs10->tx_bytes));
    oqs->tx_packets = ntohll(get_32aligned_be64(&qs10->tx_packets));
    oqs->tx_errors = ntohll(get_32aligned_be64(&qs10->tx_errors));
    oqs->duration_sec = oqs->duration_nsec = UINT32_MAX;

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_queue_stats_from_ofp11(struct ofputil_queue_stats *oqs,
                               const struct ofp11_queue_stats *qs11)
{
    enum ofperr error;

    error = ofputil_port_from_ofp11(qs11->port_no, &oqs->port_no);
    if (error) {
        return error;
    }

    oqs->queue_id = ntohl(qs11->queue_id);
    oqs->tx_bytes = ntohll(qs11->tx_bytes);
    oqs->tx_packets = ntohll(qs11->tx_packets);
    oqs->tx_errors = ntohll(qs11->tx_errors);
    oqs->duration_sec = oqs->duration_nsec = UINT32_MAX;

    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_queue_stats_from_ofp13(struct ofputil_queue_stats *oqs,
                               const struct ofp13_queue_stats *qs13)
{
    enum ofperr error = ofputil_queue_stats_from_ofp11(oqs, &qs13->qs);
    if (!error) {
        oqs->duration_sec = ntohl(qs13->duration_sec);
        oqs->duration_nsec = ntohl(qs13->duration_nsec);
    }

    return error;
}

Project: ovs
File: ofp-util.c

ofputil_queue_stats_to_ofp10(const struct ofputil_queue_stats *oqs,
                             struct ofp10_queue_stats *qs10)
{
    qs10->port_no = htons(ofp_to_u16(oqs->port_no));
    memset(qs10->pad, 0, sizeof qs10->pad);
    qs10->queue_id = htonl(oqs->queue_id);
    put_32aligned_be64(&qs10->tx_bytes, htonll(oqs->tx_bytes));
    put_32aligned_be64(&qs10->tx_packets, htonll(oqs->tx_packets));
    put_32aligned_be64(&qs10->tx_errors, htonll(oqs->tx_errors));
}

Project: ovs
File: ofp-util.c

ofputil_queue_stats_to_ofp11(const struct ofputil_queue_stats *oqs,
                             struct ofp11_queue_stats *qs11)
{
    qs11->port_no = ofputil_port_to_ofp11(oqs->port_no);
    qs11->queue_id = htonl(oqs->queue_id);
    qs11->tx_bytes = htonll(oqs->tx_bytes);
    qs11->tx_packets = htonll(oqs->tx_packets);
    qs11->tx_errors = htonll(oqs->tx_errors);
}

Project: ovs
File: ofp-util.c

ofputil_queue_stats_to_ofp13(const struct ofputil_queue_stats *oqs,
                             struct ofp13_queue_stats *qs13)
{
    ofputil_queue_stats_to_ofp11(oqs, &qs13->qs);
    if (oqs->duration_sec != UINT32_MAX) {
        qs13->duration_sec = htonl(oqs->duration_sec);
        qs13->duration_nsec = htonl(oqs->duration_nsec);
    } else {
        qs13->duration_sec = OVS_BE32_MAX;
        qs13->duration_nsec = OVS_BE32_MAX;
    }
}

Project: ovs
File: ofp-util.c

ofputil_queue_stats_to_ofp14(const struct ofputil_queue_stats *oqs,
                             struct ofp14_queue_stats *qs14)
{
    qs14->length = htons(sizeof *qs14);
    memset(qs14->pad, 0, sizeof qs14->pad);
    ofputil_queue_stats_to_ofp13(oqs, &qs14->qs);
}

Project: ovs
File: ofp-util.c

ofputil_switch_features_has_ports(struct ofpbuf *b)
{
    struct ofp_header *oh = b->data;
    size_t phy_port_size;

    if (oh->version >= OFP13_VERSION) {
        /* OpenFlow 1.3+ never has ports in the feature reply. */
        return false;
    }

    phy_port_size = (oh->version == OFP10_VERSION
                     ? sizeof(struct ofp10_phy_port)
                     : sizeof(struct ofp11_port));
    if (ntohs(oh->length) + phy_port_size <= UINT16_MAX) {
        /* There's room for additional ports in the feature reply.
         * Assume that the list is complete. */
        return true;
    }

    /* The feature reply has no room for more ports.  Probably the list is
     * truncated.  Drop the ports and tell the caller to retrieve them with
     * OFPST_PORT_DESC. */
    b->size = sizeof *oh + sizeof(struct ofp_switch_features);
    ofpmsg_update_length(b);
    return false;
}

Project: ovs
File: ofp-util.c

ofputil_tid_command(const struct ofputil_flow_mod *fm,
                    enum ofputil_protocol protocol)
{
    return htons(protocol & OFPUTIL_P_TID
                 ? (fm->command & 0xff) | (fm->table_id << 8)
                 : fm->command);
}

Project: ovs
File: ofp-util.c

ofputil_uninit_group_desc(struct ofputil_group_desc *gd)
{
    ofputil_bucket_list_destroy(&gd->buckets);
    ofputil_group_properties_destroy(&gd->props);
}

Project: ovs
File: ofp-util.c

ofputil_uninit_group_mod(struct ofputil_group_mod *gm)
{
    ofputil_bucket_list_destroy(&gm->buckets);
    ofputil_group_properties_destroy(&gm->props);
}

Project: ovs
File: ofp-util.c

ofputil_version_from_string(const char *s)
{
    if (!strcasecmp(s, "OpenFlow10")) {
        return OFP10_VERSION;
    }
    if (!strcasecmp(s, "OpenFlow11")) {
        return OFP11_VERSION;
    }
    if (!strcasecmp(s, "OpenFlow12")) {
        return OFP12_VERSION;
    }
    if (!strcasecmp(s, "OpenFlow13")) {
        return OFP13_VERSION;
    }
    if (!strcasecmp(s, "OpenFlow14")) {
        return OFP14_VERSION;
    }
    if (!strcasecmp(s, "OpenFlow15")) {
        return OFP15_VERSION;
    }
    if (!strcasecmp(s, "OpenFlow16")) {
        return OFP16_VERSION;
    }
    return 0;
}

Project: ovs
File: ofp-util.c

ofputil_version_to_string(enum ofp_version ofp_version)
{
    switch (ofp_version) {
    case OFP10_VERSION:
        return "OpenFlow10";
    case OFP11_VERSION:
        return "OpenFlow11";
    case OFP12_VERSION:
        return "OpenFlow12";
    case OFP13_VERSION:
        return "OpenFlow13";
    case OFP14_VERSION:
        return "OpenFlow14";
    case OFP15_VERSION:
        return "OpenFlow15";
    case OFP16_VERSION:
        return "OpenFlow16";
    default:
        OVS_NOT_REACHED();
    }
}

Project: ovs
File: ofp-util.c

ofputil_versions_from_strings(char ** const s, size_t count)
{
    uint32_t bitmap = 0;

    while (count--) {
        int version = ofputil_version_from_string(s[count]);
        if (!version) {
            VLOG_WARN("Unknown OpenFlow version: \"%s\"", s[count]);
        } else {
            bitmap |= 1u << version;
        }
    }

    return bitmap;
}

Project: ovs
File: ofp-util.c

ofputil_wcbits_to_netmask(int wcbits)
{
    wcbits &= 0x3f;
    return wcbits < 32 ? htonl(~((1u << wcbits) - 1)) : 0;
}

Project: ovs
File: ofp-util.c

ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
{
    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 36);

    /* Initialize most of wc. */
    flow_wildcards_init_catchall(wc);

    if (!(ofpfw & OFPFW10_IN_PORT)) {
        wc->masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX);
    }

    if (!(ofpfw & OFPFW10_NW_TOS)) {
        wc->masks.nw_tos |= IP_DSCP_MASK;
    }

    if (!(ofpfw & OFPFW10_NW_PROTO)) {
        wc->masks.nw_proto = UINT8_MAX;
    }
    wc->masks.nw_src = ofputil_wcbits_to_netmask(ofpfw
                                                 >> OFPFW10_NW_SRC_SHIFT);
    wc->masks.nw_dst = ofputil_wcbits_to_netmask(ofpfw
                                                 >> OFPFW10_NW_DST_SHIFT);

    if (!(ofpfw & OFPFW10_TP_SRC)) {
        wc->masks.tp_src = OVS_BE16_MAX;
    }
    if (!(ofpfw & OFPFW10_TP_DST)) {
        wc->masks.tp_dst = OVS_BE16_MAX;
    }

    if (!(ofpfw & OFPFW10_DL_SRC)) {
        WC_MASK_FIELD(wc, dl_src);
    }
    if (!(ofpfw & OFPFW10_DL_DST)) {
        WC_MASK_FIELD(wc, dl_dst);
    }
    if (!(ofpfw & OFPFW10_DL_TYPE)) {
        wc->masks.dl_type = OVS_BE16_MAX;
    }

    /* VLAN TCI mask. */
    if (!(ofpfw & OFPFW10_DL_VLAN_PCP)) {
        wc->masks.vlan_tci |= htons(VLAN_PCP_MASK | VLAN_CFI);
    }
    if (!(ofpfw & OFPFW10_DL_VLAN)) {
        wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI);
    }
}

Project: ovs
File: ofp-util.c

parse_action_bitmap(struct ofpbuf *payload, enum ofp_version ofp_version,
                    uint64_t *ofpacts)
{
    uint32_t types = 0;

    while (payload->size > 0) {
        enum ofperr error;
        uint64_t type;

        error = ofpprop_pull__(payload, NULL, 1, 0x10000, &type);
        if (error) {
            return error;
        }
        if (type < CHAR_BIT * sizeof types) {
            types |= 1u << type;
        }
    }

    *ofpacts = ofpact_bitmap_from_openflow(htonl(types), ofp_version);
    return 0;
}

Project: ovs
File: ofp-util.c

parse_async_tlv(const struct ofpbuf *property,
                const struct ofp14_async_prop *ap,
                struct ofputil_async_cfg *ac,
                enum ofp_version version, bool loose)
{
    enum ofperr error;
    ovs_be32 mask;

    error  = ofpprop_parse_be32(property, &mask);
    if (error) {
        return error;
    }

    if (ofpprop_is_experimenter(ap->prop_type)) {
        /* For experimenter properties, whether a property is for the master or
         * slave role is indicated by both 'type' and 'exp_type' in struct
         * ofp_prop_experimenter.  Check that these are consistent. */
        const struct ofp_prop_experimenter *ope = property->data;
        bool should_be_master = ope->type == htons(0xffff);
        if (should_be_master != ap->master) {
            VLOG_WARN_RL(&bad_ofmsg_rl, "async property type %#"PRIx16" "
                         "indicates %s role but exp_type %"PRIu32" indicates "
                         "%s role",
                         ntohs(ope->type),
                         should_be_master ? "master" : "slave",
                         ntohl(ope->exp_type),
                         ap->master ? "master" : "slave");
            return OFPERR_OFPBPC_BAD_EXP_TYPE;
        }
    }

    return decode_async_mask(mask, ap, version, loose, ac);
}

Project: ovs
File: ofp-util.c

parse_instruction_ids(struct ofpbuf *payload, bool loose, uint32_t *insts)
{
    *insts = 0;
    while (payload->size > 0) {
        enum ovs_instruction_type inst;
        enum ofperr error;
        uint64_t ofpit;

        /* OF1.3 and OF1.4 aren't clear about padding in the instruction IDs.
         * It seems clear that they aren't padded to 8 bytes, though, because
         * both standards say that "non-experimenter instructions are 4 bytes"
         * and do not mention any padding before the first instruction ID.
         * (There wouldn't be any point in padding to 8 bytes if the IDs were
         * aligned on an odd 4-byte boundary.)
         *
         * Anyway, we just assume they're all glommed together on byte
         * boundaries. */
        error = ofpprop_pull__(payload, NULL, 1, 0x10000, &ofpit);
        if (error) {
            return error;
        }

        error = ovs_instruction_type_from_inst_type(&inst, ofpit);
        if (!error) {
            *insts |= 1u << inst;
        } else if (!loose) {
            return error;
        }
    }
    return 0;
}

Project: ovs
File: ofp-util.c

parse_intel_port_stats_property(const struct ofpbuf *payload,
                                uint32_t exp_type,
                                struct ofputil_port_stats *ops)
{
    enum ofperr error;

    switch (exp_type) {
    case INTEL_PORT_STATS_RFC2819:
        error = parse_intel_port_stats_rfc2819_property(payload, ops);
        break;
    default:
        error = OFPERR_OFPBPC_BAD_EXP_TYPE;
        break;
    }

    return error;
}

Project: ovs
File: ofp-util.c

parse_intel_port_stats_rfc2819_property(const struct ofpbuf *payload,
                                        struct ofputil_port_stats *ops)
{
    const struct intel_port_stats_rfc2819 *rfc2819 = payload->data;

    if (payload->size != sizeof *rfc2819) {
        return OFPERR_OFPBPC_BAD_LEN;
    }
    ops->stats.rx_1_to_64_packets = ntohll(rfc2819->rx_1_to_64_packets);
    ops->stats.rx_65_to_127_packets = ntohll(rfc2819->rx_65_to_127_packets);
    ops->stats.rx_128_to_255_packets = ntohll(rfc2819->rx_128_to_255_packets);
    ops->stats.rx_256_to_511_packets = ntohll(rfc2819->rx_256_to_511_packets);
    ops->stats.rx_512_to_1023_packets =
        ntohll(rfc2819->rx_512_to_1023_packets);
    ops->stats.rx_1024_to_1522_packets =
        ntohll(rfc2819->rx_1024_to_1522_packets);
    ops->stats.rx_1523_to_max_packets =
        ntohll(rfc2819->rx_1523_to_max_packets);

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

    ops->stats.tx_multicast_packets = ntohll(rfc2819->tx_multicast_packets);
    ops->stats.rx_broadcast_packets = ntohll(rfc2819->rx_broadcast_packets);
    ops->stats.tx_broadcast_packets = ntohll(rfc2819->tx_broadcast_packets);
    ops->stats.rx_undersized_errors = ntohll(rfc2819->rx_undersized_errors);

    ops->stats.rx_oversize_errors = ntohll(rfc2819->rx_oversize_errors);
    ops->stats.rx_fragmented_errors = ntohll(rfc2819->rx_fragmented_errors);
    ops->stats.rx_jabber_errors = ntohll(rfc2819->rx_jabber_errors);

    return 0;
}

Project: ovs
File: ofp-util.c

parse_ofp10_queue_rate(const struct ofp10_queue_prop_header *hdr,
                       uint16_t *rate)
{
    const struct ofp10_queue_prop_rate *oqpr;

    if (hdr->len == htons(sizeof *oqpr)) {
        oqpr = (const struct ofp10_queue_prop_rate *) hdr;
        *rate = ntohs(oqpr->rate);
        return 0;
    } else {
        return OFPERR_OFPBRC_BAD_LEN;
    }
}

Project: ovs
File: ofp-util.c

parse_ofp14_port_ethernet_property(const struct ofpbuf *payload,
                                   struct ofputil_phy_port *pp)
{
    struct ofp14_port_desc_prop_ethernet *eth = payload->data;

    if (payload->size != sizeof *eth) {
        return OFPERR_OFPBPC_BAD_LEN;
    }

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

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

    return 0;
}

Project: ovs
File: ofp-util.c

parse_ofp14_port_stats_ethernet_property(const struct ofpbuf *payload,
                                         struct ofputil_port_stats *ops)
{
    const struct ofp14_port_stats_prop_ethernet *eth = payload->data;

    if (payload->size != sizeof *eth) {
        return OFPERR_OFPBPC_BAD_LEN;
    }

    ops->stats.rx_frame_errors = ntohll(eth->rx_frame_err);
    ops->stats.rx_over_errors = ntohll(eth->rx_over_err);
    ops->stats.rx_crc_errors = ntohll(eth->rx_crc_err);
    ops->stats.collisions = ntohll(eth->collisions);

    return 0;
}

Project: ovs
File: ofp-util.c

parse_ofp15_group_properties(struct ofpbuf *msg,
                             enum ofp11_group_type group_type,
                             enum ofp15_group_mod_command group_cmd,
                             struct ofputil_group_props *gp,
                             size_t properties_len)
{
    struct ofpbuf properties = ofpbuf_const_initializer(
        ofpbuf_pull(msg, properties_len), properties_len);
    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 OFPPROP_EXP(NTR_VENDOR_ID, NTRT_SELECTION_METHOD):
        case OFPPROP_EXP(NTR_COMPAT_VENDOR_ID, NTRT_SELECTION_METHOD):
            error = parse_group_prop_ntr_selection_method(&payload, group_type,
                                                          group_cmd, gp);
            break;

        default:
            error = OFPPROP_UNKNOWN(false, "group", type);
            break;
        }

        if (error) {
            return error;
        }
    }

    return 0;
}

Project: ovs
File: ofp-util.c

parse_oxms(struct ofpbuf *payload, bool loose,
           struct mf_bitmap *exactp, struct mf_bitmap *maskedp)
{
    struct mf_bitmap exact = MF_BITMAP_INITIALIZER;
    struct mf_bitmap masked = MF_BITMAP_INITIALIZER;

    while (payload->size > 0) {
        const struct mf_field *field;
        enum ofperr error;
        bool hasmask;

        error = nx_pull_header(payload, NULL, &field, &hasmask);
        if (!error) {
            bitmap_set1(hasmask ? masked.bm : exact.bm, field->id);
        } else if (error != OFPERR_OFPBMC_BAD_FIELD || !loose) {
            return error;
        }
    }
    if (exactp) {
        *exactp = exact;
    } else if (!bitmap_is_all_zeros(exact.bm, MFF_N_IDS)) {
        return OFPERR_OFPBMC_BAD_MASK;
    }
    if (maskedp) {
        *maskedp = masked;
    } else if (!bitmap_is_all_zeros(masked.bm, MFF_N_IDS)) {
        return OFPERR_OFPBMC_BAD_MASK;
    }
    return 0;
}

Project: ovs
File: ofp-util.c

parse_port_mod_ethernet_property(struct ofpbuf *property,
                                 struct ofputil_port_mod *pm)
{
    ovs_be32 advertise;
    enum ofperr error;

    error = ofpprop_parse_be32(property, &advertise);
    if (!error) {
        pm->advertise = netdev_port_features_from_ofp11(advertise);
    }
    return error;
}

Project: ovs
File: ofp-util.c

parse_stack_prop(const struct ofpbuf *property, struct ofpbuf *stack)
{
    unsigned int len = ofpbuf_msgsize(property);
    if (len > sizeof(union mf_subvalue)) {
        VLOG_WARN_RL(&bad_ofmsg_rl, "NXCPT_STACK property has bad length %u",
                     len);
        return OFPERR_OFPBPC_BAD_LEN;
    }
    nx_stack_push_bottom(stack, property->msg, len);
    return 0;
}

Project: ovs
File: ofp-util.c

parse_table_desc_vacancy_property(struct ofpbuf *property,
                                  struct ofputil_table_desc *td)
{
    struct ofp14_table_mod_prop_vacancy *otv = property->data;

    if (property->size != sizeof *otv) {
        return OFPERR_OFPBPC_BAD_LEN;
    }

    td->table_vacancy.vacancy_down = otv->vacancy_down;
    td->table_vacancy.vacancy_up = otv->vacancy_up;
    td->table_vacancy.vacancy = otv->vacancy;
    return 0;
}

Project: ovs
File: ofp-util.c

parse_table_mod_vacancy_property(struct ofpbuf *property,
                                 struct ofputil_table_mod *tm)
{
    struct ofp14_table_mod_prop_vacancy *otv = property->data;

    if (property->size != sizeof *otv) {
        return OFPERR_OFPBPC_BAD_LEN;
    }
    tm->table_vacancy.vacancy_down = otv->vacancy_down;
    tm->table_vacancy.vacancy_up = otv->vacancy_up;
    if (tm->table_vacancy.vacancy_down > tm->table_vacancy.vacancy_up) {
        OFPPROP_LOG(&bad_ofmsg_rl, false,
                    "Value of vacancy_down is greater than vacancy_up");
        return OFPERR_OFPBPC_BAD_VALUE;
    }
    if (tm->table_vacancy.vacancy_down > 100 ||
        tm->table_vacancy.vacancy_up > 100) {
        OFPPROP_LOG(&bad_ofmsg_rl, false, "Vacancy threshold percentage "
                    "should not be greater than 100");
        return OFPERR_OFPBPC_BAD_VALUE;
    }
    tm->table_vacancy.vacancy = otv->vacancy;
    if (tm->table_vacancy.vacancy) {
        OFPPROP_LOG(&bad_ofmsg_rl, false,
                    "Vacancy value should be zero for table-mod messages");
        return OFPERR_OFPBPC_BAD_VALUE;
    }
    return 0;
}

Project: ovs
File: ofp-util.c

parse_value(const char *s, const char *delimiters)
{
    size_t n = 0;

    /* Iterate until we reach a delimiter.
     *
     * strchr(s, '\0') returns s+strlen(s), so this test handles the null
     * terminator at the end of 's'.  */
    while (!strchr(delimiters, s[n])) {
        if (s[n] == '(') {
            int level = 0;
            do {
                switch (s[n]) {
                case '\0':
                    return n;
                case '(':
                    level++;
                    break;
                case ')':
                    level--;
                    break;
                }
                n++;
            } while (level > 0);
        } else {
            n++;
        }
    }
    return n;
}

Project: ovs
File: ofp-util.c

put_actions_property(struct ofpbuf *msg, uint64_t prop_type,
                     enum ofp_version version,
                     const struct ofpact *actions, size_t actions_len)
{
    if (actions_len) {
        size_t start = ofpprop_start_nested(msg, prop_type);
        ofpacts_put_openflow_actions(actions, actions_len, msg, version);
        ofpprop_end(msg, start);
    }
}

Project: ovs
File: ofp-util.c

put_fields_property(struct ofpbuf *reply,
                    const struct mf_bitmap *fields,
                    const struct mf_bitmap *masks,
                    enum ofp13_table_feature_prop_type property,
                    enum ofp_version version)
{
    size_t start_ofs;
    int field;

    start_ofs = ofpprop_start(reply, property);
    BITMAP_FOR_EACH_1 (field, MFF_N_IDS, fields->bm) {
        nx_put_header(reply, field, version,
                      masks && bitmap_is_set(masks->bm, field));
    }
    ofpprop_end(reply, start_ofs);
}

Project: ovs
File: ofp-util.c

put_ofp10_queue_rate(struct ofpbuf *reply,
                     enum ofp10_queue_properties property, uint16_t rate)
{
    if (rate != UINT16_MAX) {
        struct ofp10_queue_prop_rate *oqpr;

        oqpr = ofpbuf_put_zeros(reply, sizeof *oqpr);
        oqpr->prop_header.property = htons(property);
        oqpr->prop_header.len = htons(sizeof *oqpr);
        oqpr->rate = htons(rate);
    }
}

Project: ovs
File: ofp-util.c

put_ofp14_queue_rate(struct ofpbuf *reply,
                     enum ofp14_queue_desc_prop_type type, uint16_t rate)
{
    if (rate != UINT16_MAX) {
        ofpprop_put_u16(reply, type, rate);
    }
}

Project: ovs
File: ofp-util.c

put_table_action_features(struct ofpbuf *reply,
                          const struct ofputil_table_action_features *taf,
                          enum ofp13_table_feature_prop_type actions_type,
                          enum ofp13_table_feature_prop_type set_fields_type,
                          int miss_offset, enum ofp_version version)
{
    ofpprop_put_bitmap(reply, actions_type + miss_offset,
                       ntohl(ofpact_bitmap_to_openflow(taf->ofpacts,
                                                       version)));
    put_fields_property(reply, &taf->set_fields, NULL,
                        set_fields_type + miss_offset, version);
}

Project: ovs
File: ofp-util.c

put_table_instruction_features(
    struct ofpbuf *reply, const struct ofputil_table_instruction_features *tif,
    int miss_offset, enum ofp_version version)
{
    size_t start_ofs;
    uint8_t table_id;

    ofpprop_put_bitmap(reply, OFPTFPT13_INSTRUCTIONS + miss_offset,
                       ntohl(ovsinst_bitmap_to_openflow(tif->instructions,
                                                        version)));

    start_ofs = ofpprop_start(reply, OFPTFPT13_NEXT_TABLES + miss_offset);
    BITMAP_FOR_EACH_1 (table_id, 255, tif->next) {
        ofpbuf_put(reply, &table_id, 1);
    }
    ofpprop_end(reply, start_ofs);

    put_table_action_features(reply, &tif->write,
                              OFPTFPT13_WRITE_ACTIONS,
                              OFPTFPT13_WRITE_SETFIELD, miss_offset, version);
    put_table_action_features(reply, &tif->apply,
                              OFPTFPT13_APPLY_ACTIONS,
                              OFPTFPT13_APPLY_SETFIELD, miss_offset, version);
}

Project: ovs
File: ofp-util.c

should_send_version_bitmap(uint32_t allowed_versions)
{
    return !is_pow2((allowed_versions >> 1) + 1);
}

Project: ovs
File: ofp-util.c

unknown_to_zero(uint64_t count)
{
    return count != UINT64_MAX ? count : 0;
}

Project: ovs
File: ofp-util.c

version_bitmap_from_version(uint8_t ofp_version)
{
    return ((ofp_version < 32 ? 1u << ofp_version : 0) - 1) << 1;
}