With clarifications requested below:

Acked-by: Jarno Rajahalme <ja...@ovn.org>

> On Jan 18, 2016, at 11:27 PM, Ben Pfaff <b...@ovn.org> wrote:
> 
> Signed-off-by: Ben Pfaff <b...@ovn.org>
> ---
> lib/ofp-prop.c |  98 +++++++++++++++++++++++++++++++++++------
> lib/ofp-prop.h |  57 ++++++++++++++++++++----
> lib/ofp-util.c | 134 ++++++++++++---------------------------------------------
> 3 files changed, 160 insertions(+), 129 deletions(-)
> 
> diff --git a/lib/ofp-prop.c b/lib/ofp-prop.c
> index 2d90e1b..83d72ab 100644
> --- a/lib/ofp-prop.c
> +++ b/lib/ofp-prop.c
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2014, 2015 Nicira, Inc.
> + * Copyright (c) 2014, 2015, 2016 Nicira, Inc.
>  *
>  * Licensed under the Apache License, Version 2.0 (the "License");
>  * you may not use this file except in compliance with the License.
> @@ -21,8 +21,21 @@
> #include "byte-order.h"
> #include "ofpbuf.h"
> #include "ofp-errors.h"
> +#include "openvswitch/vlog.h"
> #include "util.h"
> 
> +static uint32_t
> +ofpprop_type_to_experimenter(uint64_t type)
> +{
> +    return type >> 32;
> +}

There are some ambiguities here. What is here termed ‘experimenter’ is 
elsewhere also called ‘experimenter ID’, and what is below termed ‘exp_id’ is 
elsewhere also called 'experimenter type’ or ‘ex_type’.

> +
> +static uint32_t
> +ofpprop_type_to_exp_id(uint64_t type)
> +{
> +    return type & UINT32_MAX;
> +}
> +
> /* Pulls a property, beginning with struct ofp_prop_header, from the beginning
>  * of 'msg'.  Stores the type of the property in '*typep' and, if 'property' 
> is
>  * nonnull, the entire property, including the header, in '*property'.  
> Returns
> @@ -33,7 +46,8 @@
>  * you can use ofpprop_pull() for that case. */
> enum ofperr
> ofpprop_pull__(struct ofpbuf *msg, struct ofpbuf *property,
> -               unsigned int alignment, uint16_t *typep)
> +               unsigned int alignment, unsigned int min_exp,

It would be nice to justify the existence of ‘min_exp’ in the comment above.

> +               uint64_t *typep)
> {
>     struct ofp_prop_header *oph;
>     unsigned int padded_len;
> @@ -50,9 +64,31 @@ ofpprop_pull__(struct ofpbuf *msg, struct ofpbuf *property,
>         return OFPERR_OFPBPC_BAD_LEN;
>     }
> 
> -    *typep = ntohs(oph->type);
> +    uint16_t type = ntohs(oph->type);
> +    if (type < min_exp) {
> +        *typep = type;
> +    } else {
> +        struct ofp_prop_experimenter *ope = msg->data;
> +        if (len < sizeof *ope) {
> +            return OFPERR_OFPBPC_BAD_LEN;
> +        }
> +
> +        if (!ope->experimenter) {
> +            /* Reject experimenter 0 because it yields ambiguity with 
> standard
> +             * property types. */
> +            return OFPERR_OFPBPC_BAD_EXPERIMENTER;
> +        }
> +
> +        *typep = OFPPROP_EXP(ntohl(ope->experimenter), ntohl(ope->exp_type));
> +    }
> +
>     if (property) {
>         ofpbuf_use_const(property, msg->data, len);
> +        msg->header = msg->data;
> +        msg->msg = ((uint8_t *) msg->data
> +                    + (type < min_exp
> +                       ? sizeof(struct ofp_prop_header)
> +                       : sizeof(struct ofp_prop_experimenter)));
>     }
>     ofpbuf_pull(msg, padded_len);
>     return 0;
> @@ -66,15 +102,15 @@ ofpprop_pull__(struct ofpbuf *msg, struct ofpbuf 
> *property,
>  * This function pulls the property's stated size padded out to a multiple of
>  * 8 bytes, which is the common case for OpenFlow properties. */
> enum ofperr
> -ofpprop_pull(struct ofpbuf *msg, struct ofpbuf *property, uint16_t *typep)
> +ofpprop_pull(struct ofpbuf *msg, struct ofpbuf *property, uint64_t *typep)
> {
> -    return ofpprop_pull__(msg, property, 8, typep);
> +    return ofpprop_pull__(msg, property, 8, 0xffff, typep);

It would be nice to document the use of '0xffff’ here.

> }
> 
> /* Adds a property with the given 'type' and 'len'-byte contents 'value' to
>  * 'msg', padding the property out to a multiple of 8 bytes. */
> void
> -ofpprop_put(struct ofpbuf *msg, uint16_t type, const void *value, size_t len)
> +ofpprop_put(struct ofpbuf *msg, uint64_t type, const void *value, size_t len)
> {
>     size_t start_ofs = ofpprop_start(msg, type);
>     ofpbuf_put(msg, value, len);
> @@ -84,7 +120,7 @@ ofpprop_put(struct ofpbuf *msg, uint16_t type, const void 
> *value, size_t len)
> /* Appends a property to 'msg' whose type is 'type' and whose contents is a
>  * series of property headers, one for each 1-bit in 'bitmap'. */
> void
> -ofpprop_put_bitmap(struct ofpbuf *msg, uint16_t type, uint64_t bitmap)
> +ofpprop_put_bitmap(struct ofpbuf *msg, uint64_t type, uint64_t bitmap)
> {
>     size_t start_ofs = ofpprop_start(msg, type);
>     for (; bitmap; bitmap = zero_rightmost_1bit(bitmap)) {
> @@ -98,14 +134,21 @@ ofpprop_put_bitmap(struct ofpbuf *msg, uint16_t type, 
> uint64_t bitmap)
>  * ofpprop_end().  Returns the offset of the beginning of the property (to 
> pass
>  * to ofpprop_end() later). */
> size_t
> -ofpprop_start(struct ofpbuf *msg, uint16_t type)
> +ofpprop_start(struct ofpbuf *msg, uint64_t type)
> {
>     size_t start_ofs = msg->size;
> -    struct ofp_prop_header *oph;
> -
> -    oph = ofpbuf_put_uninit(msg, sizeof *oph);
> -    oph->type = htons(type);
> -    oph->len = htons(4);        /* May be updated later by ofpprop_end(). */
> +    if (!ofpprop_is_experimenter(type)) {
> +        struct ofp_prop_header *oph = ofpbuf_put_uninit(msg, sizeof *oph);
> +        oph->type = htons(type);
> +        oph->len = htons(4);
> +    } else {
> +        struct ofp_prop_experimenter *ope
> +            = ofpbuf_put_uninit(msg, sizeof *ope);
> +        ope->type = htons(0xffff);
> +        ope->len = htons(12);
> +        ope->experimenter = htonl(ofpprop_type_to_experimenter(type));
> +        ope->exp_type = htonl(ofpprop_type_to_exp_id(type));
> +    }
>     return start_ofs;
> }
> 
> @@ -123,3 +166,32 @@ ofpprop_end(struct ofpbuf *msg, size_t start_ofs)
>     ofpbuf_padto(msg, ROUND_UP(msg->size, 8));
> }
> 
> +enum ofperr
> +ofpprop_unknown(struct vlog_module *module, bool loose, const char *msg,
> +                uint64_t type)
> +{
> +    bool is_experimenter = ofpprop_is_experimenter(type);
> +
> +    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
> +    enum vlog_level level = loose ? VLL_DBG : VLL_WARN;
> +    if (!is_experimenter) {
> +        vlog_rate_limit(module, level, &rl, "unknown %s property type 
> %"PRId64,
> +                        msg, type);
> +    } else {
> +        vlog_rate_limit(module, level, &rl,
> +                        "unknown %s property type for experimenter "
> +                        "0x%"PRIx32", exp_id %”PRId32,

The terminology ambiguity comment applies here as well (exp ID vs. exp type).

> +                        msg,
> +                        ofpprop_type_to_experimenter(type),
> +                        ofpprop_type_to_exp_id(type));
> +    }
> +
> +    /* There's an error OFPBPC_BAD_EXPERIMENTER that we could use for
> +     * experimenter IDs that we don't know at all, but that seems like a
> +     * difficult distinction and OFPERR_OFPBPC_BAD_EXP_TYPE communicates the
> +     * problem quite well. */
> +    return (loose ? 0
> +            : is_experimenter ? OFPERR_OFPBPC_BAD_EXP_TYPE
> +            : OFPERR_OFPBPC_BAD_TYPE);
> +}
> +
> diff --git a/lib/ofp-prop.h b/lib/ofp-prop.h
> index 07d9799..fc0c76d 100644
> --- a/lib/ofp-prop.h
> +++ b/lib/ofp-prop.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2014, 2015 Nicira, Inc.
> + * Copyright (c) 2014, 2015, 2016 Nicira, Inc.
>  *
>  * Licensed under the Apache License, Version 2.0 (the "License");
>  * you may not use this file except in compliance with the License.
> @@ -20,30 +20,64 @@
> /* OpenFlow 1.3+ property support
>  * ==============================
>  *
> - * Several OpenFlow 1.3+ messages use properties that take the common form
> - * shown by "struct ofp_prop_header".  This module provides support for
> - * serializing and deserializing properties in this format.
> + * Several OpenFlow 1.3+ messages use type-length-value (TLV) properties that
> + * take the common form shown by "struct ofp_prop_header".  This module
> + * provides support for serializing and deserializing properties in this
> + * format.
> + *
> + *
> + * Property types
> + * --------------
> + *
> + * This module uses uint64_t values to identify property types:
> + *
> + *     - OpenFlow assigns 16-bit type values to its own standardized
> + *       properties.  ofpprop uses these values directly in uint64_t.
> + *

Maybe mention that in some cases high 16-bit values denote experimenter types?

> + *     - Vendor-specific "experimenter" properties have a 32-bit 
> "experimenter
> + *       ID" (generally an Ethernet OUI) and a 32-bit experimenter-defined
> + *       "exp_type".  ofpprop encodes these with the experimenter ID in the
> + *       high 32 bits and exp_type in the low 32 bits.  (All existing
> + *       experimenter IDs are nonzero, so this is unambiguous.)  Use
> + *       OFPPROP_EXP to encode these property types.
>  */
> 
> +#include <stdbool.h>
> #include <stddef.h>
> #include <stdint.h>
> #include "ofp-errors.h"
> #include "openvswitch/types.h"
> 
> struct ofpbuf;
> +struct vlog_module;
> +
> +/* Given an OpenFlow experimenter ID (e.g. NX_VENDOR_ID) and exp_type, yields
> + * the code that ofpprop_pull() would use to identify the given experimenter
> + * property. */
> +#define OFPPROP_EXP(EXPERIMENTER, EXP_TYPE) \
> +    (((uint64_t) (EXPERIMENTER) << 32) | (EXP_TYPE))
> +
> +/* Returns true if 'type' represents an experimenter property type,
> + * false if it represents a standard property type.*/
> +static inline bool
> +ofpprop_is_experimenter(uint64_t type)
> +{
> +    return type > UINT16_MAX;
> +}
> 
> /* Deserializing properties.  */
> enum ofperr ofpprop_pull__(struct ofpbuf *msg, struct ofpbuf *property,
> -                           unsigned int alignment, uint16_t *typep);
> +                           unsigned int alignment, unsigned int min_exp,
> +                           uint64_t *typep);
> enum ofperr ofpprop_pull(struct ofpbuf *msg, struct ofpbuf *property,
> -                         uint16_t *typep);
> +                         uint64_t *typep);
> 
> /* Serializing properties. */
> -void ofpprop_put(struct ofpbuf *, uint16_t type,
> +void ofpprop_put(struct ofpbuf *, uint64_t type,
>                  const void *value, size_t len);
> -void ofpprop_put_bitmap(struct ofpbuf *, uint16_t type, uint64_t bitmap);
> +void ofpprop_put_bitmap(struct ofpbuf *, uint64_t type, uint64_t bitmap);
> 
> -size_t ofpprop_start(struct ofpbuf *, uint16_t type);
> +size_t ofpprop_start(struct ofpbuf *, uint64_t type);
> void ofpprop_end(struct ofpbuf *, size_t start_ofs);
> 
> /* Logging errors while deserializing properties.
> @@ -68,4 +102,9 @@ void ofpprop_end(struct ofpbuf *, size_t start_ofs);
> #define OFPPROP_LOG(RL, LOOSE, ...)                         \
>     VLOG_RL(RL, (LOOSE) ? VLL_DBG : VLL_WARN, __VA_ARGS__)
> 
> +enum ofperr ofpprop_unknown(struct vlog_module *, bool loose, const char 
> *msg,
> +                            uint64_t type);
> +#define OFPPROP_UNKNOWN(LOOSE, MSG, TYPE) \
> +    ofpprop_unknown(THIS_MODULE, LOOSE, MSG, TYPE)
> +
> #endif /* ofp-prop.h */
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index 05cc6d1..449f383 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -3785,7 +3785,7 @@ ofputil_pull_ofp14_port(struct ofputil_phy_port *pp, 
> struct ofpbuf *msg)
>     while (properties.size > 0) {
>         struct ofpbuf payload;
>         enum ofperr error;
> -        uint16_t type;
> +        uint64_t type;
> 
>         error = ofpprop_pull(&properties, &payload, &type);
>         if (error) {
> @@ -3798,9 +3798,7 @@ ofputil_pull_ofp14_port(struct ofputil_phy_port *pp, 
> struct ofpbuf *msg)
>             break;
> 
>         default:
> -            OFPPROP_LOG(&bad_ofmsg_rl, true,
> -                        "unknown port property %"PRIu16, type);
> -            error = 0;
> +            error = OFPPROP_UNKNOWN(true, "port", type);
>             break;
>         }
> 
> @@ -4390,7 +4388,7 @@ ofputil_decode_port_mod(const struct ofp_header *oh,
>         while (b.size > 0) {
>             struct ofpbuf property;
>             enum ofperr error;
> -            uint16_t type;
> +            uint64_t type;
> 
>             error = ofpprop_pull(&b, &property, &type);
>             if (error) {
> @@ -4403,15 +4401,7 @@ ofputil_decode_port_mod(const struct ofp_header *oh,
>                 break;
> 
>             default:
> -                OFPPROP_LOG(&bad_ofmsg_rl, loose,
> -                            "unknown port_mod property %"PRIu16, type);
> -                if (loose) {
> -                    error = 0;
> -                } else if (type == OFPPMPT14_EXPERIMENTER) {
> -                    error = OFPERR_OFPBPC_BAD_EXPERIMENTER;
> -                } else {
> -                    error = OFPERR_OFPBRC_BAD_TYPE;
> -                }
> +                error = OFPPROP_UNKNOWN(loose, "port_mod", type);
>                 break;
>             }
> 
> @@ -4496,13 +4486,13 @@ ofputil_encode_port_mod(const struct ofputil_port_mod 
> *pm,
> 
> static enum ofperr
> pull_table_feature_property(struct ofpbuf *msg, struct ofpbuf *payload,
> -                            uint16_t *typep)
> +                            uint64_t *typep)
> {
>     enum ofperr error;
> 
>     error = ofpprop_pull(msg, payload, typep);
>     if (payload && !error) {
> -        ofpbuf_pull(payload, sizeof(struct ofp_prop_header));
> +        ofpbuf_pull(payload, (uint8_t *)msg->msg - (uint8_t *)msg->header);
>     }
>     return error;
> }
> @@ -4514,10 +4504,10 @@ parse_action_bitmap(struct ofpbuf *payload, enum 
> ofp_version ofp_version,
>     uint32_t types = 0;
> 
>     while (payload->size > 0) {
> -        uint16_t type;
>         enum ofperr error;
> +        uint64_t type;
> 
> -        error = ofpprop_pull__(payload, NULL, 1, &type);
> +        error = ofpprop_pull__(payload, NULL, 1, 0x10000, &type);

It would be nice to document the significance of the value ‘0x10000’ here.

>         if (error) {
>             return error;
>         }
> @@ -4537,7 +4527,7 @@ parse_instruction_ids(struct ofpbuf *payload, bool 
> loose, uint32_t *insts)
>     while (payload->size > 0) {
>         enum ovs_instruction_type inst;
>         enum ofperr error;
> -        uint16_t ofpit;
> +        uint64_t ofpit;
> 

(snip)

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to