Fix issues with C backend with new error message hierarchy
diff --git a/c_gen/c_type_maps.py b/c_gen/c_type_maps.py
index a0fec7e..c5d69d0 100644
--- a/c_gen/c_type_maps.py
+++ b/c_gen/c_type_maps.py
@@ -67,6 +67,10 @@
out.write(" %d%s /* %s */\n" %
(type_maps.type_val[("of_stats_request", version)],
comma, cls))
+ elif cls in type_maps.error_msg_list:
+ out.write(" %d%s /* %s */\n" %
+ (type_maps.type_val[("of_error_msg", version)],
+ comma, cls))
elif cls in type_maps.flow_mod_list:
out.write(" %d%s /* %s */\n" %
(type_maps.type_val[("of_flow_mod", version)],
@@ -230,6 +234,9 @@
out.write("#include <loci/loci.h>\n\n")
# Generate maps from wire type values to object IDs
+ gen_type_to_object_id(out, "error_msg_type_to_id", "OF_ERROR_MSG",
+ "OF_%s_ERROR_MSG", type_maps.error_types,
+ max_type_value)
gen_type_to_object_id(out, "action_type_to_id", "OF_ACTION",
"OF_ACTION_%s", type_maps.action_types,
max_type_value)
@@ -384,6 +391,42 @@
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
@@ -457,6 +500,7 @@
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) {
@@ -503,6 +547,14 @@
}
}
+ 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;
}
"""
@@ -557,6 +609,12 @@
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))
@@ -725,6 +783,46 @@
""")
################################################################
+ # Generate object ID to the error sub-type map
+ ################################################################
+ out.write("""
+/**
+ * Map an object ID to an error type
+ * @param id An object ID
+ * @return The wire value for the error type
+ * @return -1 if not supported for this version
+ * @return -1 if id is not a specific error type ID
+ *
+ * Note that the value is returned as a signed integer. So -1 is
+ * an error code, while 0xffff is the usual "experimenter" code.
+ */
+
+static inline int
+of_object_to_error_type(of_object_id_t id, of_version_t version)
+{
+ if (!OF_VERSION_OKAY(version)) {
+ return -1;
+ }
+ switch (id) {""")
+ error_names = set()
+ for ver in of_g.of_version_range:
+ for name in type_maps.error_types[ver]:
+ error_names.add(name)
+ for name in error_names:
+ out.write("""
+ case OF_%(name)s_ERROR_MSG:
+ if (OF_ERROR_TYPE_%(name)s_SUPPORTED(version))
+ return OF_ERROR_TYPE_%(name)s_BY_VERSION(version);
+ break;""" % {"name": name.upper()})
+ out.write("""
+ default:
+ break;
+ }
+ return -1; /* Not recognized as error type object for this version */
+}
+""")
+
+ ################################################################
# Generate object ID to the flow mod sub-type map
################################################################
@@ -890,6 +988,10 @@
/* It's a stats obj */
of_message_stats_type_set(msg, type);
}
+ if ((type = of_object_to_error_type(id, ver)) >= 0) {
+ /* It's a stats obj */
+ of_message_error_type_set(msg, type);
+ }
if ((type = of_object_to_flow_mod_command(id, ver)) >= 0) {
/* It's a flow mod obj */
of_message_flow_mod_command_set(msg, ver, type);
diff --git a/c_gen/templates/of_message.h b/c_gen/templates/of_message.h
index 944f6d2..165fe51 100644
--- a/c_gen/templates/of_message.h
+++ b/c_gen/templates/of_message.h
@@ -45,11 +45,13 @@
#define OF_MESSAGE_LENGTH_OFFSET 2
#define OF_MESSAGE_XID_OFFSET 4
#define OF_MESSAGE_HEADER_LENGTH 8
+#define OF_MESSAGE_ERROR_TYPE_OFFSET 8
#define OF_MESSAGE_STATS_TYPE_OFFSET 8
#define OF_MESSAGE_FLOW_MOD_COMMAND_OFFSET(version) ((version) == 1 ? 56 : 25)
#define OF_MESSAGE_MIN_LENGTH 8
#define OF_MESSAGE_MIN_STATS_LENGTH (OF_MESSAGE_STATS_TYPE_OFFSET + 2)
+#define OF_MESSAGE_MIN_ERROR_LENGTH (OF_MESSAGE_ERROR_TYPE_OFFSET + 4)
#define OF_MESSAGE_MIN_FLOW_MOD_LENGTH(version) ((version) == 1 ? 57 : 26)
#define OF_MESSAGE_EXPERIMENTER_ID_OFFSET 8
@@ -177,6 +179,25 @@
buf_u16_set(msg + OF_MESSAGE_STATS_TYPE_OFFSET, type);
}
+/**
+ * @brief Get/set error type of a message
+ * @param msg Pointer to the message buffer of sufficient length
+ * @param type Data for set operation
+ * @returns get returns error type in host order
+ */
+
+static inline uint16_t
+of_message_error_type_get(of_message_t msg) {
+ uint16_t val;
+ buf_u16_get(msg + OF_MESSAGE_ERROR_TYPE_OFFSET, &val);
+ return val;
+}
+
+static inline void
+of_message_error_type_set(of_message_t msg, uint16_t type) {
+ buf_u16_set(msg + OF_MESSAGE_ERROR_TYPE_OFFSET, type);
+}
+
/**
* @brief Get/set experimenter ID of a message
diff --git a/loxi_front_end/type_maps.py b/loxi_front_end/type_maps.py
index b64f1b5..a3394b2 100644
--- a/loxi_front_end/type_maps.py
+++ b/loxi_front_end/type_maps.py
@@ -155,7 +155,7 @@
if loxi_utils.class_is_list(cls):
return True
# TODO get this from the input file when we have virtual class syntax
- if cls in ["of_flow_mod", "of_stats_request", "of_stats_reply", "of_bsn_header", "of_nicira_header", "of_action_bsn", "of_action_nicira", "of_action_id_bsn", "of_action_id_nicira"]:
+ if cls in ["of_flow_mod", "of_stats_request", "of_stats_reply", "of_error_msg", "of_bsn_header", "of_nicira_header", "of_action_bsn", "of_action_nicira", "of_action_id_bsn", "of_action_id_nicira"]:
return True
return False
@@ -169,6 +169,7 @@
message_types = {
# version 1.0
of_g.VERSION_1_0:dict(
+ error_msg = 1,
experimenter = 4,
flow_mod = 14,
stats_request = 16,
@@ -177,6 +178,7 @@
# version 1.1
of_g.VERSION_1_1:dict(
+ error_msg = 1,
experimenter = 4,
flow_mod = 14,
stats_request = 18,
@@ -185,6 +187,7 @@
# version 1.2
of_g.VERSION_1_2:dict(
+ error_msg = 1,
experimenter = 4,
flow_mod = 14,
stats_request = 18,
@@ -193,6 +196,7 @@
# version 1.3
of_g.VERSION_1_3:dict(
+ error_msg = 1,
experimenter = 4,
flow_mod = 14,
stats_request = 18, # FIXME Multipart
@@ -476,6 +480,24 @@
"of_flow_delete_strict"
]
+error_msg_list = [
+ "of_hello_failed_error_msg",
+ "of_bad_request_error_msg",
+ "of_bad_action_error_msg",
+ "of_bad_instruction_error_msg",
+ "of_bad_match_error_msg",
+ "of_flow_mod_failed_error_msg",
+ "of_group_mod_failed_error_msg",
+ "of_port_mod_failed_error_msg",
+ "of_table_mod_failed_error_msg",
+ "of_queue_op_failed_error_msg",
+ "of_switch_config_failed_error_msg",
+ "of_role_request_failed_error_msg",
+ "of_meter_mod_failed_error_msg",
+ "of_table_features_failed_error_msg",
+ "of_experimenter_error_msg"
+]
+
def sub_class_map(base_type, version):
"""
Returns an iterable object giving the instance nameys and subclass types
diff --git a/of_g.py b/of_g.py
index 651ee64..d63689f 100644
--- a/of_g.py
+++ b/of_g.py
@@ -174,7 +174,7 @@
## These members do not get normal accessors
-skip_members = ["version", "type", "length", "stats_type", "len",
+skip_members = ["version", "type", "length", "err_type", "stats_type", "len",
"type_len", "actions_len", "_command"]
## Some OpenFlow string length constants
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index 026fa60..de63eb8 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -175,7 +175,7 @@
OFPAT_SET_TP_SRC = 9,
OFPAT_SET_TP_DST = 10,
OFPAT_ENQUEUE = 11,
- OFPAT_VENDOR = 0xffff,
+ OFPAT_EXPERIMENTER = 0xffff,
};
enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
@@ -221,7 +221,7 @@
OFPST_TABLE = 3,
OFPST_PORT = 4,
OFPST_QUEUE = 5,
- OFPST_VENDOR = 0xffff,
+ OFPST_EXPERIMENTER = 0xffff,
};
enum ofp_packet_in_reason(wire_type=uint8_t) {
@@ -259,7 +259,7 @@
OFPBRC_BAD_VERSION = 0,
OFPBRC_BAD_TYPE = 1,
OFPBRC_BAD_STAT = 2,
- OFPBRC_BAD_VENDOR = 3,
+ OFPBRC_BAD_EXPERIMENTER = 3,
OFPBRC_BAD_SUBTYPE = 4,
OFPBRC_EPERM = 5,
OFPBRC_BAD_LEN = 6,
@@ -270,8 +270,8 @@
enum ofp_bad_action_code(wire_type=uint16_t) {
OFPBAC_BAD_TYPE = 0,
OFPBAC_BAD_LEN = 1,
- OFPBAC_BAD_VENDOR = 2,
- OFPBAC_BAD_VENDOR_TYPE = 3,
+ OFPBAC_BAD_EXPERIMENTER = 2,
+ OFPBAC_BAD_EXPERIMENTER_TYPE = 3,
OFPBAC_BAD_OUT_PORT = 4,
OFPBAC_BAD_ARGUMENT = 5,
OFPBAC_EPERM = 6,
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index 589d7bf..4408249 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -292,7 +292,7 @@
OFPBRC_BAD_TYPE = 1,
OFPBRC_BAD_STAT = 2,
OFPBRC_BAD_EXPERIMENTER = 3,
- OFPBRC_BAD_EXP_TYPE = 4,
+ OFPBRC_BAD_EXPERIMENTER_TYPE = 4,
OFPBRC_EPERM = 5,
OFPBRC_BAD_LEN = 6,
OFPBRC_BUFFER_EMPTY = 7,
@@ -307,7 +307,7 @@
OFPBAC_BAD_TYPE = 0,
OFPBAC_BAD_LEN = 1,
OFPBAC_BAD_EXPERIMENTER = 2,
- OFPBAC_BAD_EXP_TYPE = 3,
+ OFPBAC_BAD_EXPERIMENTER_TYPE = 3,
OFPBAC_BAD_OUT_PORT = 4,
OFPBAC_BAD_ARGUMENT = 5,
OFPBAC_EPERM = 6,
@@ -329,7 +329,7 @@
OFPBIC_UNSUP_METADATA = 3,
OFPBIC_UNSUP_METADATA_MASK = 4,
OFPBIC_BAD_EXPERIMENTER = 5,
- OFPBIC_BAD_EXP_TYPE = 6,
+ OFPBIC_BAD_EXPERIMENTER_TYPE = 6,
OFPBIC_BAD_LEN = 7,
OFPBIC_EPERM = 8,
};
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index 97adfd4..d08568a 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -338,7 +338,7 @@
OFPBRC_BAD_TYPE = 1,
OFPBRC_BAD_STAT = 2,
OFPBRC_BAD_EXPERIMENTER = 3,
- OFPBRC_BAD_EXP_TYPE = 4,
+ OFPBRC_BAD_EXPERIMENTER_TYPE = 4,
OFPBRC_EPERM = 5,
OFPBRC_BAD_LEN = 6,
OFPBRC_BUFFER_EMPTY = 7,
@@ -354,7 +354,7 @@
OFPBAC_BAD_TYPE = 0,
OFPBAC_BAD_LEN = 1,
OFPBAC_BAD_EXPERIMENTER = 2,
- OFPBAC_BAD_EXP_TYPE = 3,
+ OFPBAC_BAD_EXPERIMENTER_TYPE = 3,
OFPBAC_BAD_OUT_PORT = 4,
OFPBAC_BAD_ARGUMENT = 5,
OFPBAC_EPERM = 6,
@@ -376,7 +376,7 @@
OFPBIC_UNSUP_METADATA = 3,
OFPBIC_UNSUP_METADATA_MASK = 4,
OFPBIC_BAD_EXPERIMENTER = 5,
- OFPBIC_BAD_EXP_TYPE = 6,
+ OFPBIC_BAD_EXPERIMENTER_TYPE = 6,
OFPBIC_BAD_LEN = 7,
OFPBIC_EPERM = 8,
};
diff --git a/py_gen/templates/action.py b/py_gen/templates/action.py
index fba5294..fcfd9a5 100644
--- a/py_gen/templates/action.py
+++ b/py_gen/templates/action.py
@@ -57,12 +57,7 @@
:: #endfor
-:: if version == of_g.VERSION_1_0:
-def parse_vendor(reader):
-:: else:
def parse_experimenter(reader):
-:: #endif
-
experimenter, = reader.peek("!4xL")
if experimenter == 0x005c16c7: # Big Switch Networks
subtype, = reader.peek("!8xL")