Beispiel #1
0
def gen_type_to_object_id(out, type_str, prefix, template, value_array, max_val):
    """
    Generate C maps from various message class groups to object ids

    For each version, create an array mapping the type info to the
    object ID.  Then define an array containing those pointers.
    """

    # Create unified arrays and get length
    arr_len = type_maps.type_array_len(value_array, max_val)
    all_ars = []
    for version, val_dict in value_array.items():  # Per version dict
        ar = type_maps.dict_to_array(val_dict, max_val, type_maps.invalid_type)
        all_ars.append(ar)

    len_name = "%s_ITEM_COUNT" % prefix

    for i, ar in enumerate(all_ars):
        version = i + 1
        out.write("static const of_object_id_t\nof_%s_v%d[%s] = {\n" % (type_str, version, len_name))
        for i in range(arr_len):
            comma = ""
            if i < arr_len - 1:  # Avoid ultimate comma
                comma = ","

            # Per-version length check
            if i < len(ar):
                v = ar[i]
            else:
                v = type_maps.invalid_type

            if v == type_maps.invalid_type:
                out.write("    %-30s /* %d (Invalid) */\n" % ("OF_OBJECT_INVALID" + comma, i))
            else:
                name = (template % v.upper()) + comma
                out.write("    %-30s /* %d */\n" % (name, i))
        out.write("};\n")

    out.write(
        """
/**
 * Maps from %(c_name)s wire type values to LOCI object ids
 *
 * Indexed by wire version which is 1-based.
 */

const of_object_id_t *const of_%(name)s[OF_VERSION_ARRAY_MAX] = {
    NULL,
"""
        % dict(name=type_str, c_name=prefix.lower())
    )
    for version in of_g.of_version_range:
        out.write("    of_%(name)s_v%(version)d,\n" % dict(name=type_str, version=version))
    out.write(
        """
};

"""
        % dict(name=type_str, u_name=type_str.upper(), max_val=max_val, c_name=prefix.lower())
    )
Beispiel #2
0
def gen_type_to_obj_map_functions(out):
    """
    Generate the templated static inline type map functions
    @param out The file handle to write to
    """

    ################################################################
    # Generate all type-to-object-ID maps in a common way
    ################################################################
    map_template = """
/**
 * %(name)s wire type to object ID array.
 * Treat as private; use function accessor below
 */

extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];

#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n

/**
 * Map an %(name)s wire value to an OF object
 * @param %(name)s The %(name)s type wire value
 * @param version The version associated with the check
 * @return The %(name)s OF object type
 * @return OF_OBJECT_INVALID if type does not map to an object
 *
 */
static inline of_object_id_t
of_%(name)s_to_object_id(int %(name)s, of_version_t version)
{
    if (!OF_VERSION_OKAY(version)) {
        return OF_OBJECT_INVALID;
    }
    if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
        return OF_OBJECT_INVALID;
    }

    return of_%(name)s_type_to_id[version][%(name)s];
}
"""
    map_with_experimenter_template = """
/**
 * %(name)s wire type to object ID array.
 * Treat as private; use function accessor below
 */

extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];

#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n

/**
 * Map an %(name)s wire value to an OF object
 * @param %(name)s The %(name)s type wire value
 * @param version The version associated with the check
 * @return The %(name)s OF object type
 * @return OF_OBJECT_INVALID if type does not map to an object
 *
 */
static inline of_object_id_t
of_%(name)s_to_object_id(int %(name)s, of_version_t version)
{
    if (!OF_VERSION_OKAY(version)) {
        return OF_OBJECT_INVALID;
    }
    if (%(name)s == OF_EXPERIMENTER_TYPE) {
        return OF_%(u_name)s_EXPERIMENTER;
    }
    if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
        return OF_OBJECT_INVALID;
    }

    return of_%(name)s_type_to_id[version][%(name)s];
}
"""

    stats_template = """
/**
 * %(name)s wire type to object ID array.
 * Treat as private; use function accessor below
 */

extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];

#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n

/**
 * Map an %(name)s wire value to an OF object
 * @param %(name)s The %(name)s type wire value
 * @param version The version associated with the check
 * @return The %(name)s OF object type
 * @return OF_OBJECT_INVALID if type does not map to an object
 *
 */
static inline of_object_id_t
of_%(name)s_to_object_id(int %(name)s, of_version_t version)
{
    if (!OF_VERSION_OKAY(version)) {
        return OF_OBJECT_INVALID;
    }
    if (%(name)s == OF_EXPERIMENTER_TYPE) {
        return OF_EXPERIMENTER_%(u_name)s;
    }
    if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
        return OF_OBJECT_INVALID;
    }

    return of_%(name)s_type_to_id[version][%(name)s];
}
"""
    # Experimenter mapping functions
    # Currently we support very few candidates, so we just do a
    # list of if/elses
    experimenter_function = """
/**
 * @brief Map a message known to be an exp msg to the proper object
 *
 * Assume that the message is a vendor/experimenter message.  Determine
 * the specific object type for the message.
 * @param msg An OF message object (uint8_t *)
 * @param length The number of bytes in the message (for error checking)
 * @param version Version of message
 * @returns object ID of specific type if recognized or OF_EXPERIMENTER if not
 *
 * @todo put OF_EXPERIMENTER_<name> in loci_base.h
 */

static inline of_object_id_t
of_message_experimenter_to_object_id(of_message_t msg, of_version_t version) {
    uint32_t experimenter_id;
    uint32_t subtype;

    /* Extract experimenter and subtype value; look for match from type maps */
    experimenter_id = of_message_experimenter_id_get(msg);
    subtype = of_message_experimenter_subtype_get(msg);

    /* Do a simple if/else search for the ver, experimenter and subtype */
"""
    first = True
    for version, experimenter_lists in type_maps.extension_message_subtype.items():
        for exp, subtypes in experimenter_lists.items():
            experimenter_function += """
    if ((experimenter_id == OF_EXPERIMENTER_ID_%(exp_name)s) &&
            (version == %(ver_name)s)) {
""" % dict(exp_name=exp.upper(), ver_name=of_g.wire_ver_map[version])
            for ext_msg, subtype in subtypes.items():
                experimenter_function += """
        if (subtype == %(subtype)s) {
            return %(ext_msg)s;
        }
""" % dict(subtype=subtype, ext_msg=ext_msg.upper())
            experimenter_function += """
    }
"""
    experimenter_function += """
    return OF_EXPERIMENTER;
}
"""

    # Message need different handling
    msg_template = """
/**
 * %(name)s wire type to object ID array.
 * Treat as private; use function accessor below
 */

extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];

#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n

/**
 * Extract the type info from the message and determine its object type
 * @param msg An OF message object (uint8_t *)
 * @param length The number of bytes in the message (for error checking)
 * @returns object ID or OF_OBJECT_INVALID if parse error
 */

static inline of_object_id_t
of_message_to_object_id(of_message_t msg, int length) {
    uint8_t type;
    of_version_t ver;
    of_object_id_t obj_id;
    uint16_t stats_type;
    uint8_t flow_mod_cmd;

    if (length < OF_MESSAGE_MIN_LENGTH) {
        return OF_OBJECT_INVALID;
    }
    type = of_message_type_get(msg);
    ver = of_message_version_get(msg);
    if (!OF_VERSION_OKAY(ver)) {
        return OF_OBJECT_INVALID;
    }

    if (type >= OF_MESSAGE_ITEM_COUNT) {
        return OF_OBJECT_INVALID;
    }

    obj_id = of_message_type_to_id[ver][type];

    /* Remap to specific message if known */
    if (obj_id == OF_EXPERIMENTER) {
        if (length < OF_MESSAGE_EXPERIMENTER_MIN_LENGTH) {
            return OF_OBJECT_INVALID;
        }
        return of_message_experimenter_to_object_id(msg, ver);
    }

    /* Remap to add/delete/strict version */
    if (obj_id == OF_FLOW_MOD) {
        if (length < OF_MESSAGE_MIN_FLOW_MOD_LENGTH(ver)) {
            return OF_OBJECT_INVALID;
        }
        flow_mod_cmd = of_message_flow_mod_command_get(msg, ver);
        obj_id = of_flow_mod_to_object_id(flow_mod_cmd, ver);
    }

    if ((obj_id == OF_STATS_REQUEST) || (obj_id == OF_STATS_REPLY)) {
        if (length < OF_MESSAGE_MIN_STATS_LENGTH) {
            return OF_OBJECT_INVALID;
        }
        stats_type = of_message_stats_type_get(msg);
        if (obj_id == OF_STATS_REQUEST) {
            obj_id = of_stats_request_to_object_id(stats_type, ver);
        } else {
            obj_id = of_stats_reply_to_object_id(stats_type, ver);
        }
    }

    return obj_id;
}
"""

    # Action types array gen
    ar_len = type_maps.type_array_len(type_maps.action_types, max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="action", u_name="ACTION", ar_len=ar_len))

    # Action ID types array gen
    ar_len = type_maps.type_array_len(type_maps.action_id_types, max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="action_id", u_name="ACTION_ID", ar_len=ar_len))

    # Instruction types array gen
    ar_len = type_maps.type_array_len(type_maps.instruction_types,
                                      max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="instruction", u_name="INSTRUCTION", ar_len=ar_len))

    # Queue prop types array gen
    ar_len = type_maps.type_array_len(type_maps.queue_prop_types,
                                      max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="queue_prop", u_name="QUEUE_PROP", ar_len=ar_len))

    # Table feature prop types array gen
    ar_len = type_maps.type_array_len(type_maps.table_feature_prop_types,
                                      max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="table_feature_prop", u_name="TABLE_FEATURE_PROP",
                   ar_len=ar_len))

    # Meter band types array gen
    ar_len = type_maps.type_array_len(type_maps.meter_band_types,
                                      max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="meter_band", u_name="METER_BAND", ar_len=ar_len))

    # Hello elem types array gen
    ar_len = type_maps.type_array_len(type_maps.hello_elem_types,
                                      max_type_value)
    out.write(map_template %
              dict(name="hello_elem", u_name="HELLO_ELEM", ar_len=ar_len))

    # Stats types array gen
    ar_len = type_maps.type_array_len(type_maps.stats_types,
                                      max_type_value)
    out.write(stats_template %
              dict(name="stats_reply", u_name="STATS_REPLY", ar_len=ar_len))
    out.write(stats_template %
              dict(name="stats_request", u_name="STATS_REQUEST",
                   ar_len=ar_len))

    ar_len = type_maps.type_array_len(type_maps.flow_mod_types, max_type_value)
    out.write(map_template %
              dict(name="flow_mod", u_name="FLOW_MOD", ar_len=ar_len))

    ar_len = type_maps.type_array_len(type_maps.oxm_types, max_type_value)
    out.write("""
/* NOTE: We could optimize the OXM and only generate OF 1.2 versions. */
""")
    out.write(map_template %
              dict(name="oxm", u_name="OXM", ar_len=ar_len))

    out.write(experimenter_function)
    # Must follow stats reply/request
    ar_len = type_maps.type_array_len(type_maps.message_types, max_type_value)
    out.write(msg_template %
              dict(name="message", u_name="MESSAGE", ar_len=ar_len))
Beispiel #3
0
def gen_type_to_obj_map_functions(out):
    """
    Generate the templated static inline type map functions
    @param out The file handle to write to
    """

    ################################################################
    # Generate all type-to-object-ID maps in a common way
    ################################################################
    map_template = """
/**
 * %(name)s wire type to object ID array.
 * Treat as private; use function accessor below
 */

extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];

#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n

/**
 * Map an %(name)s wire value to an OF object
 * @param %(name)s The %(name)s type wire value
 * @param version The version associated with the check
 * @return The %(name)s OF object type
 * @return OF_OBJECT_INVALID if type does not map to an object
 *
 */
static inline of_object_id_t
of_%(name)s_to_object_id(int %(name)s, of_version_t version)
{
    if (!OF_VERSION_OKAY(version)) {
        return OF_OBJECT_INVALID;
    }
    if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
        return OF_OBJECT_INVALID;
    }

    return of_%(name)s_type_to_id[version][%(name)s];
}
"""
    map_with_experimenter_template = """
/**
 * %(name)s wire type to object ID array.
 * Treat as private; use function accessor below
 */

extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];

#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n

/**
 * Map an %(name)s wire value to an OF object
 * @param %(name)s The %(name)s type wire value
 * @param version The version associated with the check
 * @return The %(name)s OF object type
 * @return OF_OBJECT_INVALID if type does not map to an object
 *
 */
static inline of_object_id_t
of_%(name)s_to_object_id(int %(name)s, of_version_t version)
{
    if (!OF_VERSION_OKAY(version)) {
        return OF_OBJECT_INVALID;
    }
    if (%(name)s == OF_EXPERIMENTER_TYPE) {
        return OF_%(u_name)s_EXPERIMENTER;
    }
    if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
        return OF_OBJECT_INVALID;
    }

    return of_%(name)s_type_to_id[version][%(name)s];
}
"""

    stats_template = """
/**
 * %(name)s wire type to object ID array.
 * Treat as private; use function accessor below
 */

extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];

#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n

/**
 * Map an %(name)s wire value to an OF object
 * @param %(name)s The %(name)s type wire value
 * @param version The version associated with the check
 * @return The %(name)s OF object type
 * @return OF_OBJECT_INVALID if type does not map to an object
 *
 */
static inline of_object_id_t
of_%(name)s_to_object_id(int %(name)s, of_version_t version)
{
    if (!OF_VERSION_OKAY(version)) {
        return OF_OBJECT_INVALID;
    }
    if (%(name)s == OF_EXPERIMENTER_TYPE) {
        return OF_EXPERIMENTER_%(u_name)s;
    }
    if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
        return OF_OBJECT_INVALID;
    }

    return of_%(name)s_type_to_id[version][%(name)s];
}
"""

    error_msg_template = """
/**
 * %(name)s wire type to object ID array.
 * Treat as private; use function accessor below
 */

extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];

#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n

/**
 * Map an %(name)s wire value to an OF object
 * @param %(name)s The %(name)s type wire value
 * @param version The version associated with the check
 * @return The %(name)s OF object type
 * @return OF_OBJECT_INVALID if type does not map to an object
 *
 */
static inline of_object_id_t
of_error_msg_to_object_id(uint16_t %(name)s, of_version_t version)
{
    if (!OF_VERSION_OKAY(version)) {
        return OF_OBJECT_INVALID;
    }
    if (%(name)s == OF_EXPERIMENTER_TYPE) {
        return OF_EXPERIMENTER_ERROR_MSG;
    }
    if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
        return OF_OBJECT_INVALID;
    }

    return of_%(name)s_type_to_id[version][%(name)s];
}
"""

    # Experimenter mapping functions
    # Currently we support very few candidates, so we just do a
    # list of if/elses
    experimenter_function = """
/**
 * @brief Map a message known to be an exp msg to the proper object
 *
 * Assume that the message is a vendor/experimenter message.  Determine
 * the specific object type for the message.
 * @param msg An OF message object (uint8_t *)
 * @param length The number of bytes in the message (for error checking)
 * @param version Version of message
 * @returns object ID of specific type if recognized or OF_EXPERIMENTER if not
 *
 * @todo put OF_EXPERIMENTER_<name> in loci_base.h
 */

static inline of_object_id_t
of_message_experimenter_to_object_id(of_message_t msg, of_version_t version) {
    uint32_t experimenter_id;
    uint32_t subtype;

    /* Extract experimenter and subtype value; look for match from type maps */
    experimenter_id = of_message_experimenter_id_get(msg);
    subtype = of_message_experimenter_subtype_get(msg);

    /* Do a simple if/else search for the ver, experimenter and subtype */
"""
    first = True
    for version, experimenter_lists in type_maps.extension_message_subtype.items(
    ):
        for exp, subtypes in experimenter_lists.items():
            experimenter_function += """
    if ((experimenter_id == OF_EXPERIMENTER_ID_%(exp_name)s) &&
            (version == %(ver_name)s)) {
""" % dict(exp_name=exp.upper(), ver_name=of_g.wire_ver_map[version])
            for ext_msg, subtype in subtypes.items():
                experimenter_function += """
        if (subtype == %(subtype)s) {
            return %(ext_msg)s;
        }
""" % dict(subtype=subtype, ext_msg=ext_msg.upper())
            experimenter_function += """
    }
"""
    experimenter_function += """
    return OF_EXPERIMENTER;
}
"""

    # Message need different handling
    msg_template = """
/**
 * %(name)s wire type to object ID array.
 * Treat as private; use function accessor below
 */

extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];

#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n

/**
 * Extract the type info from the message and determine its object type
 * @param msg An OF message object (uint8_t *)
 * @param length The number of bytes in the message (for error checking)
 * @returns object ID or OF_OBJECT_INVALID if parse error
 */

static inline of_object_id_t
of_message_to_object_id(of_message_t msg, int length) {
    uint8_t type;
    of_version_t ver;
    of_object_id_t obj_id;
    uint16_t stats_type;
    uint16_t err_type;
    uint8_t flow_mod_cmd;

    if (length < OF_MESSAGE_MIN_LENGTH) {
        return OF_OBJECT_INVALID;
    }
    type = of_message_type_get(msg);
    ver = of_message_version_get(msg);
    if (!OF_VERSION_OKAY(ver)) {
        return OF_OBJECT_INVALID;
    }

    if (type >= OF_MESSAGE_ITEM_COUNT) {
        return OF_OBJECT_INVALID;
    }

    obj_id = of_message_type_to_id[ver][type];

    /* Remap to specific message if known */
    if (obj_id == OF_EXPERIMENTER) {
        if (length < OF_MESSAGE_EXPERIMENTER_MIN_LENGTH) {
            return OF_OBJECT_INVALID;
        }
        return of_message_experimenter_to_object_id(msg, ver);
    }

    /* Remap to add/delete/strict version */
    if (obj_id == OF_FLOW_MOD) {
        if (length < OF_MESSAGE_MIN_FLOW_MOD_LENGTH(ver)) {
            return OF_OBJECT_INVALID;
        }
        flow_mod_cmd = of_message_flow_mod_command_get(msg, ver);
        obj_id = of_flow_mod_to_object_id(flow_mod_cmd, ver);
    }

    if ((obj_id == OF_STATS_REQUEST) || (obj_id == OF_STATS_REPLY)) {
        if (length < OF_MESSAGE_MIN_STATS_LENGTH) {
            return OF_OBJECT_INVALID;
        }
        stats_type = of_message_stats_type_get(msg);
        if (obj_id == OF_STATS_REQUEST) {
            obj_id = of_stats_request_to_object_id(stats_type, ver);
        } else {
            obj_id = of_stats_reply_to_object_id(stats_type, ver);
        }
    }

    if (obj_id == OF_ERROR_MSG) {
        if (length < OF_MESSAGE_MIN_ERROR_LENGTH) {
            return OF_OBJECT_INVALID;
        }
        err_type = of_message_error_type_get(msg);
        obj_id = of_error_msg_to_object_id(err_type, ver);
    }

    return obj_id;
}
"""

    oxm_template = """
/**
 * oxm wire type to object ID array.
 * Treat as private; use function accessor below
 */

extern const of_object_id_t *const of_oxm_type_to_id[OF_VERSION_ARRAY_MAX];

#define OF_OXM_ITEM_COUNT %(ar_len)d\n

/**
 * Map an oxm wire value to an OF object
 * @param oxm The oxm type wire value
 * @param version The version associated with the check
 * @return The oxm OF object type
 * @return OF_OBJECT_INVALID if type does not map to an object
 *
 */
static inline of_object_id_t
of_oxm_to_object_id(uint32_t type_len, of_version_t version)
{
    if (!OF_VERSION_OKAY(version)) {
        return OF_OBJECT_INVALID;
    }

    uint16_t class = (type_len >> 16) & 0xffff;
    uint8_t masked_type = (type_len >> 8) & 0xff;

    if (class == 0x8000) {
        if (masked_type < 0 || masked_type >= OF_OXM_ITEM_COUNT) {
            return OF_OBJECT_INVALID;
        }

        return of_oxm_type_to_id[version][masked_type];
    } else if (class == 0x0003) {
        switch (masked_type) {
        case 0x00: return OF_OXM_BSN_IN_PORTS_128;
        case 0x01: return OF_OXM_BSN_IN_PORTS_128_MASKED;
        default: return OF_OBJECT_INVALID;
        }
    } else {
        return OF_OBJECT_INVALID;
    }
}
"""

    # Action types array gen
    ar_len = type_maps.type_array_len(type_maps.action_types, max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="action", u_name="ACTION", ar_len=ar_len))

    # Action ID types array gen
    ar_len = type_maps.type_array_len(type_maps.action_id_types,
                                      max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="action_id", u_name="ACTION_ID", ar_len=ar_len))

    # Instruction types array gen
    ar_len = type_maps.type_array_len(type_maps.instruction_types,
                                      max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="instruction", u_name="INSTRUCTION", ar_len=ar_len))

    # Queue prop types array gen
    ar_len = type_maps.type_array_len(type_maps.queue_prop_types,
                                      max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="queue_prop", u_name="QUEUE_PROP", ar_len=ar_len))

    # Table feature prop types array gen
    ar_len = type_maps.type_array_len(type_maps.table_feature_prop_types,
                                      max_type_value)
    out.write(map_with_experimenter_template % dict(
        name="table_feature_prop", u_name="TABLE_FEATURE_PROP", ar_len=ar_len))

    # Meter band types array gen
    ar_len = type_maps.type_array_len(type_maps.meter_band_types,
                                      max_type_value)
    out.write(map_with_experimenter_template %
              dict(name="meter_band", u_name="METER_BAND", ar_len=ar_len))

    # Hello elem types array gen
    ar_len = type_maps.type_array_len(type_maps.hello_elem_types,
                                      max_type_value)
    out.write(map_template %
              dict(name="hello_elem", u_name="HELLO_ELEM", ar_len=ar_len))

    # Stats types array gen
    ar_len = type_maps.type_array_len(type_maps.stats_types, max_type_value)
    out.write(stats_template %
              dict(name="stats_reply", u_name="STATS_REPLY", ar_len=ar_len))
    out.write(
        stats_template %
        dict(name="stats_request", u_name="STATS_REQUEST", ar_len=ar_len))

    ar_len = type_maps.type_array_len(type_maps.error_types, max_type_value)
    out.write(error_msg_template %
              dict(name="error_msg", u_name="ERROR_MSG", ar_len=ar_len))
    #     out.write(error_msg_function)

    ar_len = type_maps.type_array_len(type_maps.flow_mod_types, max_type_value)
    out.write(map_template %
              dict(name="flow_mod", u_name="FLOW_MOD", ar_len=ar_len))

    # OXM
    ar_len = type_maps.type_array_len(type_maps.oxm_types, max_type_value)
    out.write("""
/* NOTE: We could optimize the OXM and only generate OF 1.2 versions. */
""")
    out.write(oxm_template % dict(ar_len=ar_len))

    # Messages
    out.write(experimenter_function)
    # Must follow stats reply/request
    ar_len = type_maps.type_array_len(type_maps.message_types, max_type_value)
    out.write(msg_template %
              dict(name="message", u_name="MESSAGE", ar_len=ar_len))
Beispiel #4
0
def gen_type_to_object_id(out, type_str, prefix, template, value_array,
                          max_val):
    """
    Generate C maps from various message class groups to object ids

    For each version, create an array mapping the type info to the
    object ID.  Then define an array containing those pointers.
    """

    # Create unified arrays and get length
    arr_len = type_maps.type_array_len(value_array, max_val)
    all_ars = []
    for version, val_dict in value_array.items():  # Per version dict
        ar = type_maps.dict_to_array(val_dict, max_val, type_maps.invalid_type)
        all_ars.append(ar)

    len_name = "%s_ITEM_COUNT" % prefix

    for i, ar in enumerate(all_ars):
        version = i + 1
        out.write("static const of_object_id_t\nof_%s_v%d[%s] = {\n" %
                  (type_str, version, len_name))
        for i in range(arr_len):
            comma = ""
            if i < arr_len - 1:  # Avoid ultimate comma
                comma = ","

            # Per-version length check
            if i < len(ar):
                v = ar[i]
            else:
                v = type_maps.invalid_type

            if v == type_maps.invalid_type:
                out.write("    %-30s /* %d (Invalid) */\n" %
                          ("OF_OBJECT_INVALID" + comma, i))
            else:
                name = (template % v.upper()) + comma
                out.write("    %-30s /* %d */\n" % (name, i))
        out.write("};\n")

    out.write("""
/**
 * Maps from %(c_name)s wire type values to LOCI object ids
 *
 * Indexed by wire version which is 1-based.
 */

const of_object_id_t *const of_%(name)s[OF_VERSION_ARRAY_MAX] = {
    NULL,
""" % dict(name=type_str, c_name=prefix.lower()))
    for version in of_g.of_version_range:
        out.write("    of_%(name)s_v%(version)d,\n" %
                  dict(name=type_str, version=version))
    out.write("""
};

""" % dict(name=type_str,
           u_name=type_str.upper(),
           max_val=max_val,
           c_name=prefix.lower()))