Looks good to me.

I think it would be useful to explain why this was done in the commit message.

I think the MSG_CASE family of macros could benefit from a comment.

I think lining up the sizeof's in the switch statements is going to be
a bit annoying to maintain, I don't feel strongly about it though.

Ethan

On Thu, Sep 8, 2011 at 12:36, Ben Pfaff <b...@nicira.com> wrote:
> ---
>  lib/ofp-util.c     |  536 +++++++++++++++++++++------------------------------
>  tests/ofp-print.at |    2 +-
>  2 files changed, 222 insertions(+), 316 deletions(-)
>
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index 0a020d3..1e95d04 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -282,111 +282,80 @@ struct ofputil_msg_type {
>     unsigned int extra_multiple;
>  };
>
> -struct ofputil_msg_category {
> -    const char *name;           /* e.g. "OpenFlow message" */
> -    const struct ofputil_msg_type *types;
> -    size_t n_types;
> -    int missing_error;          /* ofp_mkerr() value for missing type. */
> +/* Represents a malformed OpenFlow message. */
> +static const struct ofputil_msg_type ofputil_invalid_type = {
> +    OFPUTIL_MSG_INVALID, 0, "OFPUTIL_MSG_INVALID", 0, 0
>  };
>
> -static bool
> -ofputil_length_ok(const struct ofputil_msg_category *cat,
> -                  const struct ofputil_msg_type *type,
> -                  unsigned int size)
> +#define MSG_CASE__(ENUM, ENUM_SUFFIX, NAME_SUFFIX, MIN_SIZE, EXTRA_MULTIPLE) 
> \
> +        case ENUM: {                                                    \
> +            static const struct ofputil_msg_type this_type = {          \
> +                OFPUTIL_##ENUM##ENUM_SUFFIX,                            \
> +                ENUM,                                                   \
> +                #ENUM NAME_SUFFIX,                                      \
> +                MIN_SIZE,                                               \
> +                EXTRA_MULTIPLE                                          \
> +            };                                                          \
> +            type = &this_type;                                          \
> +            break;                                                      \
> +        }
> +#define MSG_CASE(ENUM, MIN_SIZE, EXTRA_MULTIPLE) \
> +    MSG_CASE__(ENUM,,,                     MIN_SIZE, EXTRA_MULTIPLE)
> +#define REQ_CASE(ENUM, MIN_SIZE, EXTRA_MULTIPLE) \
> +    MSG_CASE__(ENUM, _REQUEST, " request", MIN_SIZE, EXTRA_MULTIPLE)
> +#define RPY_CASE(ENUM, MIN_SIZE, EXTRA_MULTIPLE) \
> +    MSG_CASE__(ENUM, _REPLY,   " reply",   MIN_SIZE, EXTRA_MULTIPLE)
> +
> +static int
> +ofputil_check_length(const struct ofputil_msg_type *type, unsigned int size)
>  {
>     switch (type->extra_multiple) {
>     case 0:
>         if (size != type->min_size) {
> -            VLOG_WARN_RL(&bad_ofmsg_rl, "received %s %s with incorrect "
> +            VLOG_WARN_RL(&bad_ofmsg_rl, "received %s with incorrect "
>                          "length %u (expected length %u)",
> -                         cat->name, type->name, size, type->min_size);
> -            return false;
> +                         type->name, size, type->min_size);
> +            return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
>         }
> -        return true;
> +        return 0;
>
>     case 1:
>         if (size < type->min_size) {
> -            VLOG_WARN_RL(&bad_ofmsg_rl, "received %s %s with incorrect "
> +            VLOG_WARN_RL(&bad_ofmsg_rl, "received %s with incorrect "
>                          "length %u (expected length at least %u bytes)",
> -                         cat->name, type->name, size, type->min_size);
> -            return false;
> +                         type->name, size, type->min_size);
> +            return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
>         }
> -        return true;
> +        return 0;
>
>     default:
>         if (size < type->min_size
>             || (size - type->min_size) % type->extra_multiple) {
> -            VLOG_WARN_RL(&bad_ofmsg_rl, "received %s %s with incorrect "
> +            VLOG_WARN_RL(&bad_ofmsg_rl, "received %s with incorrect "
>                          "length %u (must be exactly %u bytes or longer "
>                          "by an integer multiple of %u bytes)",
> -                         cat->name, type->name, size,
> +                         type->name, size,
>                          type->min_size, type->extra_multiple);
> -            return false;
> -        }
> -        return true;
> -    }
> -}
> -
> -static int
> -ofputil_lookup_openflow_message(const struct ofputil_msg_category *cat,
> -                                uint32_t value, unsigned int size,
> -                                const struct ofputil_msg_type **typep)
> -{
> -    const struct ofputil_msg_type *type;
> -
> -    for (type = cat->types; type < &cat->types[cat->n_types]; type++) {
> -        if (type->value == value) {
> -            if (!ofputil_length_ok(cat, type, size)) {
> -                return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> -            }
> -            *typep = type;
> -            return 0;
> +            return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
>         }
> +        return 0;
>     }
> -
> -    VLOG_WARN_RL(&bad_ofmsg_rl, "received %s of unknown type %"PRIu32,
> -                 cat->name, value);
> -    return cat->missing_error;
>  }
>
>  static int
>  ofputil_decode_vendor(const struct ofp_header *oh,
>                       const struct ofputil_msg_type **typep)
>  {
> -    static const struct ofputil_msg_type nxt_messages[] = {
> -        { OFPUTIL_NXT_ROLE_REQUEST,
> -          NXT_ROLE_REQUEST, "NXT_ROLE_REQUEST",
> -          sizeof(struct nx_role_request), 0 },
> -
> -        { OFPUTIL_NXT_ROLE_REPLY,
> -          NXT_ROLE_REPLY, "NXT_ROLE_REPLY",
> -          sizeof(struct nx_role_request), 0 },
> -
> -        { OFPUTIL_NXT_SET_FLOW_FORMAT,
> -          NXT_SET_FLOW_FORMAT, "NXT_SET_FLOW_FORMAT",
> -          sizeof(struct nxt_set_flow_format), 0 },
> -
> -        { OFPUTIL_NXT_FLOW_MOD,
> -          NXT_FLOW_MOD, "NXT_FLOW_MOD",
> -          sizeof(struct nx_flow_mod), 8 },
> -
> -        { OFPUTIL_NXT_FLOW_REMOVED,
> -          NXT_FLOW_REMOVED, "NXT_FLOW_REMOVED",
> -          sizeof(struct nx_flow_removed), 8 },
> -
> -        { OFPUTIL_NXT_FLOW_MOD_TABLE_ID,
> -          NXT_FLOW_MOD_TABLE_ID, "NXT_FLOW_MOD_TABLE_ID",
> -          sizeof(struct nxt_flow_mod_table_id), 0 },
> -    };
> -
> -    static const struct ofputil_msg_category nxt_category = {
> -        "Nicira extension message",
> -        nxt_messages, ARRAY_SIZE(nxt_messages),
> -        OFP_MKERR(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE)
> -    };
> -
> +    const char *category = "Nicira extension message";
>     const struct ofp_vendor_header *ovh;
> +    const struct ofputil_msg_type *type;
>     const struct nicira_header *nh;
> +    size_t length = ntohs(oh->length);
> +
> +    if (length < sizeof(struct ofp_vendor_header)) {
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "truncated vendor message");
> +        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> +    }
>
>     ovh = (const struct ofp_vendor_header *) oh;
>     if (ovh->vendor != htonl(NX_VENDOR_ID)) {
> @@ -395,32 +364,52 @@ ofputil_decode_vendor(const struct ofp_header *oh,
>         return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR);
>     }
>
> -    if (ntohs(ovh->header.length) < sizeof(struct nicira_header)) {
> +    if (length < sizeof(struct nicira_header)) {
>         VLOG_WARN_RL(&bad_ofmsg_rl, "received Nicira vendor message of "
> -                     "length %u (expected at least %zu)",
> -                     ntohs(ovh->header.length), sizeof(struct 
> nicira_header));
> +                     "length %zu (expected at least %zu)",
> +                     length, sizeof(struct nicira_header));
>         return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
>     }
>
>     nh = (const struct nicira_header *) oh;
> -    return ofputil_lookup_openflow_message(&nxt_category, ntohl(nh->subtype),
> -                                           ntohs(oh->length), typep);
> +    switch (ntohl(nh->subtype)) {
> +        MSG_CASE(NXT_ROLE_REQUEST,      sizeof(struct nx_role_request), 0);
> +        MSG_CASE(NXT_ROLE_REPLY,        sizeof(struct nx_role_request), 0);
> +        MSG_CASE(NXT_SET_FLOW_FORMAT,   sizeof(struct nxt_set_flow_format), 
> 0);
> +        MSG_CASE(NXT_FLOW_MOD,          sizeof(struct nx_flow_mod), 8);
> +        MSG_CASE(NXT_FLOW_REMOVED,      sizeof(struct nx_flow_removed), 8);
> +        MSG_CASE(NXT_FLOW_MOD_TABLE_ID, sizeof(struct nxt_flow_mod_table_id),
> +                 0);
> +
> +    default:
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "received %s of unknown type %"PRIu32,
> +                     category, ntohl(nh->subtype));
> +        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE);
> +    }
> +
> +    *typep = type;
> +    return 0;
>  }
>
>  static int
>  check_nxstats_msg(const struct ofp_header *oh)
>  {
> -    const struct ofp_stats_msg *osm = (const struct ofp_stats_msg *) oh;
> -    ovs_be32 vendor;
> +    const struct ofp_vendor_stats_msg *ovsm;
> +    size_t length = ntohs(oh->length);
> +
> +    if (length < sizeof(struct ofp_vendor_stats_msg)) {
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "truncated vendor stats message");
> +        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> +    }
>
> -    memcpy(&vendor, osm + 1, sizeof vendor);
> -    if (vendor != htonl(NX_VENDOR_ID)) {
> +    ovsm = (const struct ofp_vendor_stats_msg *) oh;
> +    if (ovsm->vendor != htonl(NX_VENDOR_ID)) {
>         VLOG_WARN_RL(&bad_ofmsg_rl, "received vendor stats message for "
> -                     "unknown vendor %"PRIx32, ntohl(vendor));
> +                     "unknown vendor %"PRIx32, ntohl(ovsm->vendor));
>         return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR);
>     }
>
> -    if (ntohs(osm->header.length) < sizeof(struct nicira_stats_msg)) {
> +    if (length < sizeof(struct nicira_stats_msg)) {
>         VLOG_WARN_RL(&bad_ofmsg_rl, "truncated Nicira stats message");
>         return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
>     }
> @@ -432,22 +421,8 @@ static int
>  ofputil_decode_nxst_request(const struct ofp_header *oh,
>                             const struct ofputil_msg_type **typep)
>  {
> -    static const struct ofputil_msg_type nxst_requests[] = {
> -        { OFPUTIL_NXST_FLOW_REQUEST,
> -          NXST_FLOW, "NXST_FLOW request",
> -          sizeof(struct nx_flow_stats_request), 8 },
> -
> -        { OFPUTIL_NXST_AGGREGATE_REQUEST,
> -          NXST_AGGREGATE, "NXST_AGGREGATE request",
> -          sizeof(struct nx_aggregate_stats_request), 8 },
> -    };
> -
> -    static const struct ofputil_msg_category nxst_request_category = {
> -        "Nicira extension statistics request",
> -        nxst_requests, ARRAY_SIZE(nxst_requests),
> -        OFP_MKERR(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE)
> -    };
> -
> +    const char *category = "Nicira extension statistics request";
> +    const struct ofputil_msg_type *type;
>     const struct nicira_stats_msg *nsm;
>     int error;
>
> @@ -457,31 +432,26 @@ ofputil_decode_nxst_request(const struct ofp_header *oh,
>     }
>
>     nsm = (struct nicira_stats_msg *) oh;
> -    return ofputil_lookup_openflow_message(&nxst_request_category,
> -                                           ntohl(nsm->subtype),
> -                                           ntohs(oh->length), typep);
> +    switch (ntohl(nsm->subtype)) {
> +        REQ_CASE(NXST_FLOW,      sizeof(struct nx_flow_stats_request), 8);
> +        REQ_CASE(NXST_AGGREGATE, sizeof(struct nx_aggregate_stats_request), 
> 8);
> +
> +    default:
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "received %s of unknown type %"PRIu32,
> +                     category, ntohl(nsm->subtype));
> +        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE);
> +    }
> +
> +    *typep = type;
> +    return 0;
>  }
>
>  static int
>  ofputil_decode_nxst_reply(const struct ofp_header *oh,
>                           const struct ofputil_msg_type **typep)
>  {
> -    static const struct ofputil_msg_type nxst_replies[] = {
> -        { OFPUTIL_NXST_FLOW_REPLY,
> -          NXST_FLOW, "NXST_FLOW reply",
> -          sizeof(struct nicira_stats_msg), 8 },
> -
> -        { OFPUTIL_NXST_AGGREGATE_REPLY,
> -          NXST_AGGREGATE, "NXST_AGGREGATE reply",
> -          sizeof(struct nx_aggregate_stats_reply), 0 },
> -    };
> -
> -    static const struct ofputil_msg_category nxst_reply_category = {
> -        "Nicira extension statistics reply",
> -        nxst_replies, ARRAY_SIZE(nxst_replies),
> -        OFP_MKERR(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE)
> -    };
> -
> +    const char *category = "Nicira extension statistics reply";
> +    const struct ofputil_msg_type *type;
>     const struct nicira_stats_msg *nsm;
>     int error;
>
> @@ -491,115 +461,156 @@ ofputil_decode_nxst_reply(const struct ofp_header *oh,
>     }
>
>     nsm = (struct nicira_stats_msg *) oh;
> -    return ofputil_lookup_openflow_message(&nxst_reply_category,
> -                                           ntohl(nsm->subtype),
> -                                           ntohs(oh->length), typep);
> +    switch (ntohl(nsm->subtype)) {
> +        RPY_CASE(NXST_FLOW,      sizeof(struct nicira_stats_msg), 8);
> +        RPY_CASE(NXST_AGGREGATE, sizeof(struct nx_aggregate_stats_reply), 0);
> +
> +    default:
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "received %s of unknown type %"PRIu32,
> +                     category, ntohl(nsm->subtype));
> +        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE);
> +    }
> +
> +    *typep = type;
> +    return 0;
>  }
>
>  static int
> -ofputil_decode_ofpst_request(const struct ofp_header *oh,
> -                             const struct ofputil_msg_type **typep)
> +check_stats_msg(const struct ofp_header *oh)
>  {
> -    static const struct ofputil_msg_type ofpst_requests[] = {
> -        { OFPUTIL_OFPST_DESC_REQUEST,
> -          OFPST_DESC, "OFPST_DESC request",
> -          sizeof(struct ofp_stats_msg), 0 },
> -
> -        { OFPUTIL_OFPST_FLOW_REQUEST,
> -          OFPST_FLOW, "OFPST_FLOW request",
> -          sizeof(struct ofp_flow_stats_request), 0 },
> +    size_t length = ntohs(oh->length);
>
> -        { OFPUTIL_OFPST_AGGREGATE_REQUEST,
> -          OFPST_AGGREGATE, "OFPST_AGGREGATE request",
> -          sizeof(struct ofp_flow_stats_request), 0 },
> -
> -        { OFPUTIL_OFPST_TABLE_REQUEST,
> -          OFPST_TABLE, "OFPST_TABLE request",
> -          sizeof(struct ofp_stats_msg), 0 },
> +    if (length < sizeof(struct ofp_stats_msg)) {
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "truncated stats message");
> +        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> +    }
>
> -        { OFPUTIL_OFPST_PORT_REQUEST,
> -          OFPST_PORT, "OFPST_PORT request",
> -          sizeof(struct ofp_port_stats_request), 0 },
> +    return 0;
> +}
>
> -        { OFPUTIL_OFPST_QUEUE_REQUEST,
> -          OFPST_QUEUE, "OFPST_QUEUE request",
> -          sizeof(struct ofp_queue_stats_request), 0 },
> +static int
> +ofputil_decode_ofpst_request(const struct ofp_header *oh,
> +                             const struct ofputil_msg_type **typep)
> +{
> +    const char *category = "OpenFlow statistics";
> +    const struct ofp_stats_msg *request = (const struct ofp_stats_msg *) oh;
> +    const struct ofputil_msg_type *type;
> +    int error;
>
> -        { 0,
> -          OFPST_VENDOR, "OFPST_VENDOR request",
> -          sizeof(struct ofp_vendor_stats_msg), 1 },
> -    };
> +    error = check_stats_msg(oh);
> +    if (error) {
> +        return error;
> +    }
>
> -    static const struct ofputil_msg_category ofpst_request_category = {
> -        "OpenFlow statistics",
> -        ofpst_requests, ARRAY_SIZE(ofpst_requests),
> -        OFP_MKERR(OFPET_BAD_REQUEST, OFPBRC_BAD_STAT)
> -    };
> +    switch (ntohs(request->type)) {
> +        REQ_CASE(OFPST_DESC,      sizeof(struct ofp_stats_msg), 0);
> +        REQ_CASE(OFPST_FLOW,      sizeof(struct ofp_flow_stats_request), 0);
> +        REQ_CASE(OFPST_AGGREGATE, sizeof(struct ofp_flow_stats_request), 0);
> +        REQ_CASE(OFPST_TABLE,     sizeof(struct ofp_stats_msg), 0);
> +        REQ_CASE(OFPST_PORT,      sizeof(struct ofp_port_stats_request), 0);
> +        REQ_CASE(OFPST_QUEUE,     sizeof(struct ofp_queue_stats_request), 0);
>
> -    const struct ofp_stats_msg *request = (const struct ofp_stats_msg *) oh;
> -    int error;
> +    case OFPST_VENDOR:
> +        return ofputil_decode_nxst_request(oh, typep);
>
> -    error = ofputil_lookup_openflow_message(&ofpst_request_category,
> -                                            ntohs(request->type),
> -                                            ntohs(oh->length), typep);
> -    if (!error && request->type == htons(OFPST_VENDOR)) {
> -        error = ofputil_decode_nxst_request(oh, typep);
> +    default:
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "received %s of unknown type %"PRIu16,
> +                     category, ntohs(request->type));
> +        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_STAT);
>     }
> -    return error;
> +
> +    *typep = type;
> +    return 0;
>  }
>
>  static int
>  ofputil_decode_ofpst_reply(const struct ofp_header *oh,
>                            const struct ofputil_msg_type **typep)
>  {
> -    static const struct ofputil_msg_type ofpst_replies[] = {
> -        { OFPUTIL_OFPST_DESC_REPLY,
> -          OFPST_DESC, "OFPST_DESC reply",
> -          sizeof(struct ofp_desc_stats), 0 },
> -
> -        { OFPUTIL_OFPST_FLOW_REPLY,
> -          OFPST_FLOW, "OFPST_FLOW reply",
> -          sizeof(struct ofp_stats_msg), 1 },
> -
> -        { OFPUTIL_OFPST_AGGREGATE_REPLY,
> -          OFPST_AGGREGATE, "OFPST_AGGREGATE reply",
> -          sizeof(struct ofp_aggregate_stats_reply), 0 },
> +    const char *category = "OpenFlow statistics";
> +    const struct ofp_stats_msg *reply = (const struct ofp_stats_msg *) oh;
> +    const struct ofputil_msg_type *type;
> +    int error;
>
> -        { OFPUTIL_OFPST_TABLE_REPLY,
> -          OFPST_TABLE, "OFPST_TABLE reply",
> -          sizeof(struct ofp_stats_msg), sizeof(struct ofp_table_stats) },
> +    error = check_stats_msg(oh);
> +    if (error) {
> +        return error;
> +    }
>
> -        { OFPUTIL_OFPST_PORT_REPLY,
> -          OFPST_PORT, "OFPST_PORT reply",
> -          sizeof(struct ofp_stats_msg), sizeof(struct ofp_port_stats) },
> +    switch (ntohs(reply->type)) {
> +        RPY_CASE(OFPST_DESC,      sizeof(struct ofp_desc_stats), 0);
> +        RPY_CASE(OFPST_FLOW,      sizeof(struct ofp_stats_msg), 1);
> +        RPY_CASE(OFPST_AGGREGATE, sizeof(struct ofp_aggregate_stats_reply), 
> 0);
> +        RPY_CASE(OFPST_TABLE,     sizeof(struct ofp_stats_msg),
> +                 sizeof(struct ofp_table_stats));
> +        RPY_CASE(OFPST_PORT,      sizeof(struct ofp_stats_msg),
> +                 sizeof(struct ofp_port_stats));
> +        RPY_CASE(OFPST_QUEUE,     sizeof(struct ofp_stats_msg),
> +                 sizeof(struct ofp_queue_stats));
>
> -        { OFPUTIL_OFPST_QUEUE_REPLY,
> -          OFPST_QUEUE, "OFPST_QUEUE reply",
> -          sizeof(struct ofp_stats_msg), sizeof(struct ofp_queue_stats) },
> +    case OFPST_VENDOR:
> +        return ofputil_decode_nxst_reply(oh, typep);
>
> -        { 0,
> -          OFPST_VENDOR, "OFPST_VENDOR reply",
> -          sizeof(struct ofp_vendor_stats_msg), 1 },
> -    };
> +    default:
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "received %s of unknown type %"PRIu16,
> +                     category, ntohs(reply->type));
> +        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_STAT);
> +    }
>
> -    static const struct ofputil_msg_category ofpst_reply_category = {
> -        "OpenFlow statistics",
> -        ofpst_replies, ARRAY_SIZE(ofpst_replies),
> -        OFP_MKERR(OFPET_BAD_REQUEST, OFPBRC_BAD_STAT)
> -    };
> +    *typep = type;
> +    return 0;
> +}
>
> -    const struct ofp_stats_msg *reply = (const struct ofp_stats_msg *) oh;
> +static int
> +ofputil_decode_msg_type__(const struct ofp_header *oh,
> +                          const struct ofputil_msg_type **typep)
> +{
> +    const char *category = "OpenFlow message";
> +    const struct ofputil_msg_type *type;
>     int error;
>
> -    error = ofputil_lookup_openflow_message(&ofpst_reply_category,
> -                                           ntohs(reply->type),
> -                                           ntohs(oh->length), typep);
> -    if (!error && reply->type == htons(OFPST_VENDOR)) {
> -        error = ofputil_decode_nxst_reply(oh, typep);
> +    error = 0;
> +    switch (oh->type) {
> +        MSG_CASE(OFPT_HELLO,              sizeof(struct ofp_hello), 1);
> +        MSG_CASE(OFPT_ERROR,              sizeof(struct ofp_error_msg), 1);
> +        MSG_CASE(OFPT_ECHO_REQUEST,       sizeof(struct ofp_header), 1);
> +        MSG_CASE(OFPT_ECHO_REPLY,         sizeof(struct ofp_header), 1);
> +        MSG_CASE(OFPT_FEATURES_REQUEST,   sizeof(struct ofp_header), 0);
> +        MSG_CASE(OFPT_FEATURES_REPLY,     sizeof(struct ofp_switch_features),
> +                 sizeof(struct ofp_phy_port));
> +        MSG_CASE(OFPT_GET_CONFIG_REQUEST, sizeof(struct ofp_header), 0);
> +        MSG_CASE(OFPT_GET_CONFIG_REPLY,   sizeof(struct ofp_switch_config), 
> 0);
> +        MSG_CASE(OFPT_SET_CONFIG,         sizeof(struct ofp_switch_config), 
> 0);
> +        MSG_CASE(OFPT_PACKET_IN,          offsetof(struct ofp_packet_in, 
> data),
> +                 1);
> +        MSG_CASE(OFPT_FLOW_REMOVED,       sizeof(struct ofp_flow_removed), 
> 0);
> +        MSG_CASE(OFPT_PORT_STATUS,        sizeof(struct ofp_port_status), 0);
> +        MSG_CASE(OFPT_PACKET_OUT,         sizeof(struct ofp_packet_out), 1);
> +        MSG_CASE(OFPT_FLOW_MOD,           sizeof(struct ofp_flow_mod), 1);
> +        MSG_CASE(OFPT_PORT_MOD,           sizeof(struct ofp_port_mod), 0);
> +        MSG_CASE(OFPT_BARRIER_REQUEST,    sizeof(struct ofp_header), 0);
> +        MSG_CASE(OFPT_BARRIER_REPLY,      sizeof(struct ofp_header), 0);
> +
> +    case OFPT_STATS_REQUEST:
> +        return ofputil_decode_ofpst_request(oh, typep);
> +
> +    case OFPT_STATS_REPLY:
> +        return ofputil_decode_ofpst_reply(oh, typep);
> +
> +    case OFPT_VENDOR:
> +        return ofputil_decode_vendor(oh, typep);
> +
> +    default:
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "received %s of unknown type %"PRIu8,
> +                     category, oh->type);
> +        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE);
>     }
> -    return error;
> +
> +    *typep = type;
> +    return 0;
>  }
>
> +
>  /* Decodes the message type represented by 'oh'.  Returns 0 if successful or
>  * an OpenFlow error code constructed with ofp_mkerr() on failure.  Either
>  * way, stores in '*typep' a type structure that can be inspected with the
> @@ -614,114 +625,9 @@ int
>  ofputil_decode_msg_type(const struct ofp_header *oh,
>                         const struct ofputil_msg_type **typep)
>  {
> -    static const struct ofputil_msg_type ofpt_messages[] = {
> -        { OFPUTIL_OFPT_HELLO,
> -          OFPT_HELLO, "OFPT_HELLO",
> -          sizeof(struct ofp_hello), 1 },
> -
> -        { OFPUTIL_OFPT_ERROR,
> -          OFPT_ERROR, "OFPT_ERROR",
> -          sizeof(struct ofp_error_msg), 1 },
> -
> -        { OFPUTIL_OFPT_ECHO_REQUEST,
> -          OFPT_ECHO_REQUEST, "OFPT_ECHO_REQUEST",
> -          sizeof(struct ofp_header), 1 },
> -
> -        { OFPUTIL_OFPT_ECHO_REPLY,
> -          OFPT_ECHO_REPLY, "OFPT_ECHO_REPLY",
> -          sizeof(struct ofp_header), 1 },
> -
> -        { OFPUTIL_OFPT_FEATURES_REQUEST,
> -          OFPT_FEATURES_REQUEST, "OFPT_FEATURES_REQUEST",
> -          sizeof(struct ofp_header), 0 },
> -
> -        { OFPUTIL_OFPT_FEATURES_REPLY,
> -          OFPT_FEATURES_REPLY, "OFPT_FEATURES_REPLY",
> -          sizeof(struct ofp_switch_features), sizeof(struct ofp_phy_port) },
> -
> -        { OFPUTIL_OFPT_GET_CONFIG_REQUEST,
> -          OFPT_GET_CONFIG_REQUEST, "OFPT_GET_CONFIG_REQUEST",
> -          sizeof(struct ofp_header), 0 },
> -
> -        { OFPUTIL_OFPT_GET_CONFIG_REPLY,
> -          OFPT_GET_CONFIG_REPLY, "OFPT_GET_CONFIG_REPLY",
> -          sizeof(struct ofp_switch_config), 0 },
> -
> -        { OFPUTIL_OFPT_SET_CONFIG,
> -          OFPT_SET_CONFIG, "OFPT_SET_CONFIG",
> -          sizeof(struct ofp_switch_config), 0 },
> -
> -        { OFPUTIL_OFPT_PACKET_IN,
> -          OFPT_PACKET_IN, "OFPT_PACKET_IN",
> -          offsetof(struct ofp_packet_in, data), 1 },
> -
> -        { OFPUTIL_OFPT_FLOW_REMOVED,
> -          OFPT_FLOW_REMOVED, "OFPT_FLOW_REMOVED",
> -          sizeof(struct ofp_flow_removed), 0 },
> -
> -        { OFPUTIL_OFPT_PORT_STATUS,
> -          OFPT_PORT_STATUS, "OFPT_PORT_STATUS",
> -          sizeof(struct ofp_port_status), 0 },
> -
> -        { OFPUTIL_OFPT_PACKET_OUT,
> -          OFPT_PACKET_OUT, "OFPT_PACKET_OUT",
> -          sizeof(struct ofp_packet_out), 1 },
> -
> -        { OFPUTIL_OFPT_FLOW_MOD,
> -          OFPT_FLOW_MOD, "OFPT_FLOW_MOD",
> -          sizeof(struct ofp_flow_mod), 1 },
> -
> -        { OFPUTIL_OFPT_PORT_MOD,
> -          OFPT_PORT_MOD, "OFPT_PORT_MOD",
> -          sizeof(struct ofp_port_mod), 0 },
> -
> -        { 0,
> -          OFPT_STATS_REQUEST, "OFPT_STATS_REQUEST",
> -          sizeof(struct ofp_stats_msg), 1 },
> -
> -        { 0,
> -          OFPT_STATS_REPLY, "OFPT_STATS_REPLY",
> -          sizeof(struct ofp_stats_msg), 1 },
> -
> -        { OFPUTIL_OFPT_BARRIER_REQUEST,
> -          OFPT_BARRIER_REQUEST, "OFPT_BARRIER_REQUEST",
> -          sizeof(struct ofp_header), 0 },
> -
> -        { OFPUTIL_OFPT_BARRIER_REPLY,
> -          OFPT_BARRIER_REPLY, "OFPT_BARRIER_REPLY",
> -          sizeof(struct ofp_header), 0 },
> -
> -        { 0,
> -          OFPT_VENDOR, "OFPT_VENDOR",
> -          sizeof(struct ofp_vendor_header), 1 },
> -    };
> -
> -    static const struct ofputil_msg_category ofpt_category = {
> -        "OpenFlow message",
> -        ofpt_messages, ARRAY_SIZE(ofpt_messages),
> -        OFP_MKERR(OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE)
> -    };
> -
> -    int error;
> -
> -    error = ofputil_lookup_openflow_message(&ofpt_category, oh->type,
> -                                            ntohs(oh->length), typep);
> +    int error = ofputil_decode_msg_type__(oh, typep);
>     if (!error) {
> -        switch (oh->type) {
> -        case OFPT_VENDOR:
> -            error = ofputil_decode_vendor(oh, typep);
> -            break;
> -
> -        case OFPT_STATS_REQUEST:
> -            error = ofputil_decode_ofpst_request(oh, typep);
> -            break;
> -
> -        case OFPT_STATS_REPLY:
> -            error = ofputil_decode_ofpst_reply(oh, typep);
> -
> -        default:
> -            break;
> -        }
> +        error = ofputil_check_length(*typep, ntohs(oh->length));
>     }
>     if (error) {
>         static const struct ofputil_msg_type ofputil_invalid_type = {
> diff --git a/tests/ofp-print.at b/tests/ofp-print.at
> index c2018c7..d293348 100644
> --- a/tests/ofp-print.at
> +++ b/tests/ofp-print.at
> @@ -197,7 +197,7 @@ ff fe 50 54 00 00 00 01 62 72 30 00 00 00 00 00 \
>  000000d0  00 00 02 08 00 00 02 8f-00 00 02 8f             |............    |
>  ], [stderr])
>  AT_CHECK([sed 's/.*|//' stderr], [0], [dnl
> -received OpenFlow message OFPT_FEATURES_REPLY with incorrect length 220 
> (must be exactly 32 bytes or longer by an integer multiple of 48 bytes)
> +received OFPT_FEATURES_REPLY with incorrect length 220 (must be exactly 32 
> bytes or longer by an integer multiple of 48 bytes)
>  ])
>  AT_CLEANUP
>
> --
> 1.7.4.4
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to