Removed error category types (OFPERR_OFPET_*) from enum ofperr to make it harder for contributors to use unencodable error codes. Removed corresponding functions ofperr_is_category() and ofperr_decode_type(). Added OFPERR_NX__UNKNOWN_ERROR (NX1.0+(0xfffe,256)), which is now encoded if the error code given to ofperr_encode_msg__() cannot be encoded with the given ofp_version. The rationale is that the corresponding OF transaction has failed, and the controller must know this, so sending no error message is not an option. Changed ofperr_encode_msg__() logging from WARN to ERR, as using unencodable error codes for the underlying openflow version is an error. Added OFPERR_NXBRC_FM_BAD_EVENT to avoid using an unencodable error code in ofputil_decode_flow_update(). Replaced unencodable error codes in ofp-actions.c with encodable ones.
Signed-off-by: Jarno Rajahalme <jarno.rajaha...@nsn.com> --- build-aux/extract-ofp-errors | 22 +--------------------- lib/ofp-actions.c | 7 ++++--- lib/ofp-errors.c | 77 ++++++++++++++++++++++++++++++++------------------------------------------- lib/ofp-errors.h | 60 +++++++++++++--------------------------------------------- lib/ofp-util.c | 2 +- tests/ofp-actions.at | 4 ++-- 6 files changed, 54 insertions(+), 118 deletions(-) diff --git a/build-aux/extract-ofp-errors b/build-aux/extract-ofp-errors index c327304..fd53001 100755 --- a/build-aux/extract-ofp-errors +++ b/build-aux/extract-ofp-errors @@ -294,7 +294,6 @@ struct ofperr_domain { const char *name; uint8_t version; enum ofperr (*decode)(uint16_t type, uint16_t code); - enum ofperr (*decode_type)(uint16_t type); struct pair errors[OFPERR_N_ERRORS]; }; @@ -333,24 +332,6 @@ static enum ofperr } return 0; -} - -static enum ofperr -%s_decode_type(uint16_t type) -{ - switch (type) {""" % name - for enum in names: - if enum not in map: - continue - type_, code = map[enum] - if code is not None: - continue - print " case %d:" % type_ - print " return OFPERR_%s;" % enum - print """\ - } - - return 0; }""" print """ @@ -358,8 +339,7 @@ static const struct ofperr_domain %s = { "%s", %d, %s_decode, - %s_decode_type, - {""" % (name, description, version, name, name) + {""" % (name, description, version, name) for enum in names: if enum in map: type_, code = map[enum] diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 170e796..c20a521 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -718,7 +718,7 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out) if (((const struct ofp11_action_push *)a)->ethertype != htons(ETH_TYPE_VLAN_8021Q)) { /* TODO:XXX 802.1AD(QinQ) isn't supported at the moment */ - return OFPERR_OFPET_BAD_ACTION; + return OFPERR_OFPBAC_BAD_ARGUMENT; } ofpact_put_PUSH_VLAN(out); break; @@ -912,7 +912,9 @@ decode_openflow11_instructions(const struct ofp11_instruction insts[], } if (out[type]) { - return OFPERR_OFPIT_BAD_INSTRUCTION; + return OFPERR_OFPBAC_UNSUPPORTED_ORDER; /* No specific code for + * a duplicate instruction + * exist */ } out[type] = inst; } @@ -1152,7 +1154,6 @@ ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len) if (om) { if (a->type == OFPACT_WRITE_METADATA) { VLOG_WARN("duplicate write_metadata instruction specified"); - /* should be OFPERR_OFPET_BAD_ACTION? */ return OFPERR_OFPBAC_UNSUPPORTED_ORDER; } else { VLOG_WARN("write_metadata instruction must be specified after " diff --git a/lib/ofp-errors.c b/lib/ofp-errors.c index 9fd48fe..c09aa4e 100644 --- a/lib/ofp-errors.c +++ b/lib/ofp-errors.c @@ -53,17 +53,6 @@ ofperr_is_valid(enum ofperr error) return error >= OFPERR_OFS && error < OFPERR_OFS + OFPERR_N_ERRORS; } -/* Returns true if 'error' is a valid OFPERR_* value that designates a whole - * category of errors instead of a particular error, e.g. if it is an - * OFPERR_OFPET_* value, and false otherwise. */ -bool -ofperr_is_category(enum ofperr error) -{ - return (ofperr_is_valid(error) - && ofperr_of10.errors[error - OFPERR_OFS].code == -1 - && ofperr_of11.errors[error - OFPERR_OFS].code == -1); -} - /* Returns true if 'error' is a valid OFPERR_* value that is a Nicira * extension, e.g. if it is an OFPERR_NX* value, and false otherwise. */ bool @@ -71,7 +60,9 @@ ofperr_is_nx_extension(enum ofperr error) { return (ofperr_is_valid(error) && (ofperr_of10.errors[error - OFPERR_OFS].code >= 0x100 || - ofperr_of11.errors[error - OFPERR_OFS].code >= 0x100)); + ofperr_of11.errors[error - OFPERR_OFS].code >= 0x100 || + ofperr_of12.errors[error - OFPERR_OFS].code >= 0x100 || + ofperr_of13.errors[error - OFPERR_OFS].code >= 0x100)); } /* Returns true if 'error' can be encoded as an OpenFlow error message in @@ -97,16 +88,6 @@ ofperr_decode(enum ofp_version version, uint16_t type, uint16_t code) return domain ? domain->decode(type, code) : 0; } -/* Returns the OFPERR_* value that corresponds to the category 'type' within - * 'version', or 0 if either no such OFPERR_* value exists or 'version' is - * unknown. */ -enum ofperr -ofperr_decode_type(enum ofp_version version, uint16_t type) -{ - const struct ofperr_domain *domain = ofperr_domain_from_version(version); - return domain ? domain->decode_type(type) : 0; -} - /* Returns the name of 'error', e.g. "OFPBRC_BAD_TYPE" if 'error' is * OFPBRC_BAD_TYPE, or "<invalid>" if 'error' is not a valid OFPERR_* value. * @@ -167,33 +148,45 @@ ofperr_encode_msg__(enum ofperr error, enum ofp_version ofp_version, struct ofpbuf *buf; const struct ofperr_domain *domain; + /* + * This corresponds to OFPERR_NX__UNKNOWN_ERROR, and is here + * to make sure we always have this, even if we have failed + * to implement an error domain for the ofp_version in use. + */ + static const struct pair unknown_error = { 0xfffe, 256 }; + domain = ofperr_domain_from_version(ofp_version); - if (!domain) { - return NULL; - } if (!ofperr_is_encodable(error, ofp_version)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); - if (!ofperr_is_valid(error)) { + if (!domain) { + VLOG_ERR_RL(&rl, "Error domain for %s does not exist, " + "Cannot encode error (%s)", + ofputil_version_to_string(ofp_version), + ofperr_get_name(error)); + } else if (!ofperr_is_valid(error)) { /* 'error' seems likely to be a system errno value. */ - VLOG_WARN_RL(&rl, "invalid OpenFlow error code %d (%s)", - error, strerror(error)); + VLOG_ERR_RL(&rl, "invalid OpenFlow error code %d (%s)", + error, strerror(error)); } else { - const char *s = ofperr_get_name(error); - if (ofperr_is_category(error)) { - VLOG_WARN_RL(&rl, "cannot encode error category (%s)", s); - } else { - VLOG_WARN_RL(&rl, "cannot encode %s for %s", s, domain->name); - } + VLOG_ERR_RL(&rl, "cannot encode %s for %s", + ofperr_get_name(error), domain->name); } - return NULL; + /* The caller expects the controller to get an error message, + * must send something! */ + error = OFPERR_NX__UNKNOWN_ERROR; + VLOG_WARN_RL(&rl, "Substituting with generic error %s", + ofperr_get_name(error)); + pair = &unknown_error; + } + else { /* error is encodable => domain exists */ + pair = ofperr_get_pair__(error, domain); } - pair = ofperr_get_pair__(error, domain); if (!ofperr_is_nx_extension(error)) { - buf = ofpraw_alloc_xid(OFPRAW_OFPT_ERROR, domain->version, xid, + buf = ofpraw_alloc_xid(OFPRAW_OFPT_ERROR, ofp_version, xid, sizeof *oem + data_len); oem = ofpbuf_put_uninit(buf, sizeof *oem); @@ -202,7 +195,7 @@ ofperr_encode_msg__(enum ofperr error, enum ofp_version ofp_version, } else { struct nx_vendor_error *nve; - buf = ofpraw_alloc_xid(OFPRAW_OFPT_ERROR, domain->version, xid, + buf = ofpraw_alloc_xid(OFPRAW_OFPT_ERROR, ofp_version, xid, sizeof *oem + sizeof *nve + data_len); oem = ofpbuf_put_uninit(buf, sizeof *oem); @@ -295,7 +288,7 @@ ofperr_get_code(enum ofperr error, enum ofp_version version) return domain ? ofperr_get_pair__(error, domain)->code : -1; } -/* Tries to decodes 'oh', which should be an OpenFlow OFPT_ERROR message. +/* Tries to decode 'oh', which should be an OpenFlow OFPT_ERROR message. * Returns an OFPERR_* constant on success, 0 on failure. * * If 'payload' is nonnull, on success '*payload' is initialized to the @@ -341,12 +334,8 @@ ofperr_decode_msg(const struct ofp_header *oh, struct ofpbuf *payload) code = ntohs(nve->code); } - /* Translate the error type and code into an ofperr. - * If we don't know the error type and code, at least try for the type. */ + /* Translate the error type and code into an ofperr. */ error = ofperr_decode(oh->version, type, code); - if (!error) { - error = ofperr_decode_type(oh->version, type); - } if (error && payload) { ofpbuf_use_const(payload, b.data, b.size); } diff --git a/lib/ofp-errors.h b/lib/ofp-errors.h index e9fedb9..49e2d58 100644 --- a/lib/ofp-errors.h +++ b/lib/ofp-errors.h @@ -68,11 +68,8 @@ enum ofperr { /* ## OFPET_HELLO_FAILED ## */ /* ## ------------------ ## */ - /* OF1.0+(0). Hello protocol failed. */ - OFPERR_OFPET_HELLO_FAILED = OFPERR_OFS, - /* OF1.0+(0,0). No compatible version. */ - OFPERR_OFPHFC_INCOMPATIBLE, + OFPERR_OFPHFC_INCOMPATIBLE = OFPERR_OFS, /* OF1.0+(0,1). Permissions error. */ OFPERR_OFPHFC_EPERM, @@ -81,9 +78,6 @@ enum ofperr { /* ## OFPET_BAD_REQUEST ## */ /* ## ----------------- ## */ - /* OF1.0+(1). Request was not understood. */ - OFPERR_OFPET_BAD_REQUEST, - /* OF1.0+(1,0). ofp_header.version not supported. */ OFPERR_OFPBRC_BAD_VERSION, @@ -161,13 +155,15 @@ enum ofperr { * the id of any existing monitor. */ OFPERR_NXBRC_FM_BAD_ID, + /* NX1.0+(1,520). The 'event' in an NXST_FLOW_MONITOR reply does not + * specify one of the NXFME_ABBREV, NXFME_ADD, NXFME_DELETE, or + * NXFME_MODIFY. */ + OFPERR_NXBRC_FM_BAD_EVENT, + /* ## ---------------- ## */ /* ## OFPET_BAD_ACTION ## */ /* ## ---------------- ## */ - /* OF1.0+(2). Error in action description. */ - OFPERR_OFPET_BAD_ACTION, - /* OF1.0+(2,0). Unknown action type. */ OFPERR_OFPBAC_BAD_TYPE, @@ -224,9 +220,6 @@ enum ofperr { /* ## OFPET_BAD_INSTRUCTION ## */ /* ## --------------------- ## */ - /* OF1.1+(3). Error in instruction list. */ - OFPERR_OFPIT_BAD_INSTRUCTION, - /* OF1.1+(3,0). Unknown instruction. */ OFPERR_OFPBIC_UNKNOWN_INST, @@ -258,9 +251,6 @@ enum ofperr { /* ## OFPET_BAD_MATCH ## */ /* ## --------------- ## */ - /* OF1.1+(4). Error in match. */ - OFPERR_OFPET_BAD_MATCH, - /* OF1.1+(4,0). Unsupported match type specified by the match */ OFPERR_OFPBMC_BAD_TYPE, @@ -306,9 +296,6 @@ enum ofperr { /* ## OFPET_FLOW_MOD_FAILED ## */ /* ## --------------------- ## */ - /* OF1.0(3), OF1.1+(5). Problem modifying flow entry. */ - OFPERR_OFPET_FLOW_MOD_FAILED, - /* OF1.1+(5,0). Unspecified error. */ OFPERR_OFPFMFC_UNKNOWN, @@ -354,9 +341,6 @@ enum ofperr { /* ## OFPET_GROUP_MOD_FAILED ## */ /* ## ---------------------- ## */ - /* OF1.1+(6). Problem modifying group entry. */ - OFPERR_OFPET_GROUP_MOD_FAILED, - /* OF1.1+(6,0). Group not added because a group ADD attempted to replace * an already-present group. */ OFPERR_OFPGMFC_GROUP_EXISTS, @@ -412,9 +396,6 @@ enum ofperr { /* ## OFPET_PORT_MOD_FAILED ## */ /* ## --------------------- ## */ - /* OF1.0(4), OF1.1+(7). OFPT_PORT_MOD failed. */ - OFPERR_OFPET_PORT_MOD_FAILED, - /* OF1.0(4,0), OF1.1+(7,0). Specified port does not exist. */ OFPERR_OFPPMFC_BAD_PORT, @@ -435,9 +416,6 @@ enum ofperr { /* ## OFPET_TABLE_MOD_FAILED ## */ /* ## ---------------------- ## */ - /* OF1.1+(8). Table mod request failed. */ - OFPERR_OFPET_TABLE_MOD_FAILED, - /* OF1.1+(8,0). Specified table does not exist. */ OFPERR_OFPTMFC_BAD_TABLE, @@ -451,9 +429,6 @@ enum ofperr { /* ## OFPET_QUEUE_OP_FAILED ## */ /* ## --------------------- ## */ - /* OF1.0(5), OF1.1+(9). Queue operation failed. */ - OFPERR_OFPET_QUEUE_OP_FAILED, - /* OF1.0(5,0), OF1.1+(9,0). Invalid port (or port does not exist). */ OFPERR_OFPQOFC_BAD_PORT, @@ -467,9 +442,6 @@ enum ofperr { /* ## OFPET_SWITCH_CONFIG_FAILED ## */ /* ## -------------------------- ## */ - /* OF1.1+(10). Switch config request failed. */ - OFPERR_OFPET_SWITCH_CONFIG_FAILED, - /* OF1.1+(10,0). Specified flags is invalid. */ OFPERR_OFPSCFC_BAD_FLAGS, @@ -483,9 +455,6 @@ enum ofperr { /* ## OFPET_ROLE_REQUEST_FAILED ## */ /* ## ------------------------- ## */ - /* OF1.2+(11). Controller Role request failed. */ - OFPERR_OFPET_ROLE_REQUEST_FAILED, - /* OF1.2+(11,0). Stale Message: old generation_id. */ OFPERR_OFPRRFC_STALE, @@ -499,9 +468,6 @@ enum ofperr { /* ## OFPET_METER_MOD_FAILED ## */ /* ## ---------------------- ## */ - /* OF1.3+(12). Error in meter. */ - OFPERR_OFPET_METER_MOD_FAILED, - /* OF1.3+(12,0). Unspecified error. */ OFPERR_OFPMMFC_UNKNOWN, @@ -545,9 +511,6 @@ enum ofperr { /* ## OFPET_TABLE_FEATURES_FAILED ## */ /* ## --------------------------- ## */ - /* OF1.3+(13). Setting table features failed. */ - OFPERR_OFPET_TABLE_FEATURES_FAILED, - /* OF1.3+(13,0). Specified table does not exist. */ OFPERR_OFPTFFC_BAD_TABLE, @@ -566,23 +529,26 @@ enum ofperr { /* OF1.3+(13,5). Permissions error. */ OFPERR_OFPTFFC_EPERM, +/* ## ----------------- ## */ +/* ## NX__UNKNOWN_ERROR ## */ +/* ## ----------------- ## */ + + /* NX1.0+(0xfffe,256). The switch failed to encode a specific error code. + * The operation referred to has failed due to an unknown reason. */ + OFPERR_NX__UNKNOWN_ERROR, + /* ## ------------------ ## */ /* ## OFPET_EXPERIMENTER ## */ /* ## ------------------ ## */ - - /* OF1.2+(0xffff). Experimenter error messages. */ - OFPERR_OFPET_EXPERIMENTER, }; const char *ofperr_domain_get_name(enum ofp_version); bool ofperr_is_valid(enum ofperr); -bool ofperr_is_category(enum ofperr); bool ofperr_is_nx_extension(enum ofperr); bool ofperr_is_encodable(enum ofperr, enum ofp_version); enum ofperr ofperr_decode(enum ofp_version, uint16_t type, uint16_t code); -enum ofperr ofperr_decode_type(enum ofp_version, uint16_t type); enum ofperr ofperr_from_name(const char *); enum ofperr ofperr_decode_msg(const struct ofp_header *, diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 49cbe2d..348c6fc 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -3681,7 +3681,7 @@ ofputil_decode_flow_update(struct ofputil_flow_update *update, VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR reply has bad event %"PRIu16, ntohs(nfuh->event)); - return OFPERR_OFPET_BAD_REQUEST; + return OFPERR_NXBRC_FM_BAD_EVENT; } bad_len: diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at index e232435..503900f 100644 --- a/tests/ofp-actions.at +++ b/tests/ofp-actions.at @@ -341,7 +341,7 @@ dnl Check that an empty Apply-Actions instruction gets dropped. 0004 0008 00000000 dnl Duplicate instruction type: -# bad OF1.1 instructions: OFPIT_BAD_INSTRUCTION +# bad OF1.1 instructions: OFPBAC_UNSUPPORTED_ORDER 0004 0008 00000000 0004 0008 00000000 dnl Instructions not multiple of 8 in length. @@ -379,7 +379,7 @@ dnl Write-Metadata too long. 0002 0020 00000000 fedcba9876543210 ffffffffffffffff 0000000000000000 dnl Write-Metadata duplicated. -# bad OF1.1 instructions: OFPIT_BAD_INSTRUCTION +# bad OF1.1 instructions: OFPBAC_UNSUPPORTED_ORDER 0002 0018 00000000 fedcba9876543210 ff00ff00ff00ff00 0002 0018 00000000 fedcba9876543210 ff00ff00ff00ff00 dnl Write-Metadata in wrong position.
_______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev