[ovs-dev] [of1.1 3/3] Better abstract OpenFlow error codes.
Ethan Jackson
ethan at nicira.com
Thu Jan 12 23:17:56 UTC 2012
This looks like a big win. Couple of comments.
My compiler complains about this patch:
ofproto/ofproto.c: In function ‘ofoperation_complete’:
ofproto/ofproto.c:3157:5: error: comparison of unsigned expression >=
0 is always true [-Werror=type-limits]
In ofperr_encode_msg__() the following line:
pair = &domain->errors[MIN(error - OFPERR_OFS, OFPERR_N_ERRORS)];
I don't think you need the MIN because you know at this point that
'error' is valid and therefore error - OFPERR_OFS is less than
OFPERR_N_ERRORS.
Also in the same function you have a cast without a space following it.
Ethan
On Wed, Dec 14, 2011 at 10:01, Ben Pfaff <blp at nicira.com> wrote:
> This commit switches from using the actual protocol values of error codes
> internally in Open vSwitch, to using abstract values that are translated to
> and from protocol values at message parsing and serialization time. I
> believe that this makes the code easier to read and to write.
>
> This is also one step along the way toward OpenFlow 1.1 support because
> OpenFlow 1.1 renumbered a bunch of error codes.
> ---
> build-aux/extract-ofp-errors | 243 ++++++++++++++++++--------
> include/openflow/openflow.h | 77 ---------
> lib/.gitignore | 2 +-
> lib/automake.mk | 13 +-
> lib/autopath.c | 5 +-
> lib/autopath.h | 4 +-
> lib/bundle.c | 22 ++-
> lib/bundle.h | 5 +-
> lib/dpif.c | 10 +-
> lib/learn.c | 27 ++--
> lib/learn.h | 4 +-
> lib/learning-switch.c | 1 +
> lib/multipath.c | 7 +-
> lib/multipath.h | 6 +-
> lib/nx-match.c | 48 ++----
> lib/nx-match.h | 16 +-
> lib/ofp-errors.c | 286 +++++++++++++++++++++++++++++++
> lib/ofp-errors.h | 389 +++++++++++++++++++++++++++++++++++++++++-
> lib/ofp-print.c | 40 ++---
> lib/ofp-util.c | 363 +++++++++-------------------------------
> lib/ofp-util.h | 174 ++-----------------
> lib/vconn.c | 11 +-
> ofproto/connmgr.c | 21 +--
> ofproto/connmgr.h | 7 +-
> ofproto/ofproto-dpif.c | 19 +-
> ofproto/ofproto-provider.h | 49 +++---
> ofproto/ofproto.c | 145 ++++++++--------
> ofproto/pktbuf.c | 13 +-
> ofproto/pktbuf.h | 8 +-
> tests/ofp-print.at | 57 +++++-
> tests/ovs-ofctl.at | 92 +++++-----
> utilities/ovs-ofctl.c | 7 +-
> 32 files changed, 1261 insertions(+), 910 deletions(-)
> create mode 100644 lib/ofp-errors.c
>
> diff --git a/build-aux/extract-ofp-errors b/build-aux/extract-ofp-errors
> index c34888f..5c3cd26 100755
> --- a/build-aux/extract-ofp-errors
> +++ b/build-aux/extract-ofp-errors
> @@ -12,6 +12,15 @@ idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
> tokenRe = "#?" + idRe + "|[0-9]+|."
> inComment = False
> inDirective = False
> +
> +def getLine():
> + global line
> + global lineNumber
> + line = inputFile.readline()
> + lineNumber += 1
> + if line == "":
> + fatal("unexpected end of input")
> +
> def getToken():
> global token
> global line
> @@ -58,7 +67,7 @@ def getToken():
> return False
>
> def fatal(msg):
> - sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
> + sys.stderr.write("%s:%d: %s\n" % (fileName, lineNumber, msg))
> sys.exit(1)
>
> def skipDirective():
> @@ -124,95 +133,179 @@ This program reads the header files specified on the command line and
> outputs a C source file for translating OpenFlow error codes into
> strings, for use as lib/ofp-errors.c in the Open vSwitch source tree.
>
> -This program is specialized for reading include/openflow/openflow.h
> -and include/openflow/nicira-ext.h. It will not work on arbitrary
> -header files without extensions.''' % {"argv0": argv0}
> +This program is specialized for reading lib/ofp-errors.h. It will not
> +work on arbitrary header files without extensions.\
> +''' % {"argv0": argv0}
> sys.exit(0)
>
> def extract_ofp_errors(filenames):
> error_types = {}
>
> + comments = []
> + names = []
> + domain = {}
> + reverse = {}
> + for domain_name in ("OF1.0", "OF1.1", "NX1.0", "NX1.1"):
> + domain[domain_name] = {}
> + reverse[domain_name] = {}
> +
> global fileName
> for fileName in filenames:
> global inputFile
> global lineNumber
> inputFile = open(fileName)
> lineNumber = 0
> - while getToken():
> - if token in ("#ifdef", "#ifndef", "#include",
> - "#endif", "#elif", "#else", '#define'):
> - skipDirective()
> - elif match('enum'):
> - forceId()
> - enum_tag = token
> - getToken()
> -
> - forceMatch("{")
> -
> - constants = []
> - while isId(token):
> - constants.append(token)
> - getToken()
> - if match('='):
> - while token != ',' and token != '}':
> - getToken()
> - match(',')
> -
> - forceMatch('}')
> -
> - if enum_tag == "ofp_error_type":
> - error_types = {}
> - for error_type in constants:
> - error_types[error_type] = []
> - elif enum_tag == 'nx_vendor_code':
> - pass
> - elif enum_tag.endswith('_code'):
> - error_type = 'OFPET_%s' % '_'.join(enum_tag.split('_')[1:-1]).upper()
> - if error_type not in error_types:
> - fatal("enum %s looks like an error code enumeration but %s is unknown" % (enum_tag, error_type))
> - error_types[error_type] += constants
> - elif token in ('struct', 'union'):
> - getToken()
> - forceId()
> - getToken()
> - forceMatch('{')
> - while not match('}'):
> - getToken()
> - elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
> - while token != ';':
> - getToken()
> - else:
> - fatal("parse error")
> +
> + while True:
> + getLine()
> + if re.match('enum ofperr', line):
> + break
> +
> + while True:
> + getLine()
> + if line.startswith('/*') or not line or line.isspace():
> + continue
> + elif re.match('}', line):
> + break
> +
> + m = re.match('\s+/\* ((?:.(?!\. ))+.)\. (.*)$', line)
> + if not m:
> + fatal("unexpected syntax between errors")
> +
> + dsts, comment = m.groups()
> +
> + comment.rstrip()
> + while not comment.endswith('*/'):
> + getLine()
> + if line.startswith('/*') or not line or line.isspace():
> + fatal("unexpected syntax within error")
> + comment += ' %s' % line.lstrip('* \t').rstrip(' \t\r\n')
> + comment = comment[:-2].rstrip()
> +
> + getLine()
> + m = re.match('\s+(?:OFPERR_((?:OFP|NX)[A-Z0-9_]+))(\s*=\s*OFPERR_OFS)?,',
> + line)
> + if not m:
> + fatal("syntax error expecting enum value")
> +
> + enum = m.group(1)
> +
> + comments.append(comment)
> + names.append(enum)
> +
> + for dst in dsts.split(', '):
> + m = re.match(r'([A-Z0-9.]+)\((\d+)(?:,(\d+))?\)$', dst)
> + if not m:
> + fatal("%s: syntax error in destination" % dst)
> + targets = m.group(1)
> + type_ = int(m.group(2))
> + if m.group(3):
> + code = int(m.group(3))
> + else:
> + code = None
> +
> + target_map = {"OF": ("OF1.0", "OF1.1"),
> + "OF1.0": ("OF1.0",),
> + "OF1.1": ("OF1.1",),
> + "NX": ("OF1.0", "OF1.1"),
> + "NX1.0": ("OF1.0",),
> + "NX1.1": ("OF1.1",)}
> + if targets not in target_map:
> + fatal("%s: unknown error domain" % target)
> + for target in target_map[targets]:
> + if type_ not in domain[target]:
> + domain[target][type_] = {}
> + if code in domain[target][type_]:
> + fatal("%s: duplicate assignment in domain" % dst)
> + domain[target][type_][code] = enum
> + reverse[target][enum] = (type_, code)
> +
> inputFile.close()
>
> - print "/* -*- buffer-read-only: t -*- */"
> - print "#include <config.h>"
> - print '#include "ofp-errors.h"'
> - print "#include <inttypes.h>"
> - print "#include <stdio.h>"
> - for fileName in sys.argv[1:]:
> - print '#include "%s"' % fileName
> - print '#include "type-props.h"'
> -
> - for error_type, constants in sorted(error_types.items()):
> - tag = 'ofp_%s_code' % re.sub('^OFPET_', '', error_type).lower()
> - print_enum(tag, constants, "static ")
> - print_enum("ofp_error_type", error_types.keys(), "")
> - print """
> -const char *
> -ofp_error_code_to_string(uint16_t type, uint16_t code)
> -{
> - switch (type) {\
> -"""
> - for error_type in error_types:
> - tag = 'ofp_%s_code' % re.sub('^OFPET_', '', error_type).lower()
> - print " case %s:" % error_type
> - print " return %s_to_string(code);" % tag
> print """\
> +/* Generated automatically; do not modify! -*- buffer-read-only: t -*- */
> +
> +#define OFPERR_N_ERRORS %d
> +
> +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];
> +};
> +
> +static const char *error_names[OFPERR_N_ERRORS] = {
> +%s
> +};
> +
> +static const char *error_comments[OFPERR_N_ERRORS] = {
> +%s
> +};\
> +""" % (len(names),
> + '\n'.join(' "%s",' % name for name in names),
> + '\n'.join(' "%s",' % re.sub(r'(["\\])', r'\\\1', comment)
> + for comment in comments))
> +
> + def output_domain(map, name, description, version):
> + print """
> +static enum ofperr
> +%s_decode(uint16_t type, uint16_t code)
> +{
> + switch ((type << 16) | code) {""" % name
> + for enum in names:
> + if enum not in map:
> + continue
> + type_, code = map[enum]
> + if code is None:
> + continue
> + print " case (%d << 16) | %d:" % (type_, code)
> + print " return OFPERR_%s;" % enum
> + print """\
> }
> - return NULL;
> -}\
> -"""
> +
> + 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 """
> +const struct ofperr_domain %s = {
> + "%s",
> + %d,
> + %s_decode,
> + %s_decode_type,
> + {""" % (name, description, version, name, name)
> + for enum in names:
> + if enum in map:
> + type_, code = map[enum]
> + if code == None:
> + code = -1
> + else:
> + type_ = code = -1
> + print " { %2d, %3d }, /* %s */" % (type_, code, enum)
> + print """\
> + },
> +};"""
> +
> + output_domain(reverse["OF1.0"], "ofperr_of10", "OpenFlow 1.0", 0x01)
> + output_domain(reverse["OF1.1"], "ofperr_of11", "OpenFlow 1.1", 0x02)
>
> if __name__ == '__main__':
> if '--help' in sys.argv:
> diff --git a/include/openflow/openflow.h b/include/openflow/openflow.h
> index f260984..f68a140 100644
> --- a/include/openflow/openflow.h
> +++ b/include/openflow/openflow.h
> @@ -603,83 +603,6 @@ struct ofp_flow_removed {
> };
> OFP_ASSERT(sizeof(struct ofp_flow_removed) == 88);
>
> -/* Values for 'type' in ofp_error_message. These values are immutable: they
> - * will not change in future versions of the protocol (although new values may
> - * be added). */
> -enum ofp_error_type {
> - OFPET_HELLO_FAILED, /* Hello protocol failed. */
> - OFPET_BAD_REQUEST, /* Request was not understood. */
> - OFPET_BAD_ACTION, /* Error in action description. */
> - OFPET_FLOW_MOD_FAILED, /* Problem modifying flow entry. */
> - OFPET_PORT_MOD_FAILED, /* OFPT_PORT_MOD failed. */
> - OFPET_QUEUE_OP_FAILED /* Queue operation failed. */
> -};
> -
> -/* ofp_error_msg 'code' values for OFPET_HELLO_FAILED. 'data' contains an
> - * ASCII text string that may give failure details. */
> -enum ofp_hello_failed_code {
> - OFPHFC_INCOMPATIBLE, /* No compatible version. */
> - OFPHFC_EPERM /* Permissions error. */
> -};
> -
> -/* ofp_error_msg 'code' values for OFPET_BAD_REQUEST. 'data' contains at least
> - * the first 64 bytes of the failed request. */
> -enum ofp_bad_request_code {
> - OFPBRC_BAD_VERSION, /* ofp_header.version not supported. */
> - OFPBRC_BAD_TYPE, /* ofp_header.type not supported. */
> - OFPBRC_BAD_STAT, /* ofp_stats_msg.type not supported. */
> - OFPBRC_BAD_VENDOR, /* Vendor not supported (in ofp_vendor_header
> - * or ofp_stats_msg). */
> - OFPBRC_BAD_SUBTYPE, /* Vendor subtype not supported. */
> - OFPBRC_EPERM, /* Permissions error. */
> - OFPBRC_BAD_LEN, /* Wrong request length for type. */
> - OFPBRC_BUFFER_EMPTY, /* Specified buffer has already been used. */
> - OFPBRC_BUFFER_UNKNOWN /* Specified buffer does not exist. */
> -};
> -
> -/* ofp_error_msg 'code' values for OFPET_BAD_ACTION. 'data' contains at least
> - * the first 64 bytes of the failed request. */
> -enum ofp_bad_action_code {
> - OFPBAC_BAD_TYPE, /* Unknown action type. */
> - OFPBAC_BAD_LEN, /* Length problem in actions. */
> - OFPBAC_BAD_VENDOR, /* Unknown vendor id specified. */
> - OFPBAC_BAD_VENDOR_TYPE, /* Unknown action type for vendor id. */
> - OFPBAC_BAD_OUT_PORT, /* Problem validating output action. */
> - OFPBAC_BAD_ARGUMENT, /* Bad action argument. */
> - OFPBAC_EPERM, /* Permissions error. */
> - OFPBAC_TOO_MANY, /* Can't handle this many actions. */
> - OFPBAC_BAD_QUEUE /* Problem validating output queue. */
> -};
> -
> -/* ofp_error_msg 'code' values for OFPET_FLOW_MOD_FAILED. 'data' contains
> - * at least the first 64 bytes of the failed request. */
> -enum ofp_flow_mod_failed_code {
> - OFPFMFC_ALL_TABLES_FULL, /* Flow not added because of full tables. */
> - OFPFMFC_OVERLAP, /* Attempted to add overlapping flow with
> - * CHECK_OVERLAP flag set. */
> - OFPFMFC_EPERM, /* Permissions error. */
> - OFPFMFC_BAD_EMERG_TIMEOUT, /* Flow not added because of non-zero idle/hard
> - * timeout. */
> - OFPFMFC_BAD_COMMAND, /* Unknown command. */
> - OFPFMFC_UNSUPPORTED /* Unsupported action list - cannot process in
> - the order specified. */
> -};
> -
> -/* ofp_error_msg 'code' values for OFPET_PORT_MOD_FAILED. 'data' contains
> - * at least the first 64 bytes of the failed request. */
> -enum ofp_port_mod_failed_code {
> - OFPPMFC_BAD_PORT, /* Specified port does not exist. */
> - OFPPMFC_BAD_HW_ADDR, /* Specified hardware address is wrong. */
> -};
> -
> -/* ofp_error msg 'code' values for OFPET_QUEUE_OP_FAILED. 'data' contains
> - * at least the first 64 bytes of the failed request */
> -enum ofp_queue_op_failed_code {
> - OFPQOFC_BAD_PORT, /* Invalid port (or port does not exist). */
> - OFPQOFC_BAD_QUEUE, /* Queue does not exist. */
> - OFPQOFC_EPERM /* Permissions error. */
> -};
> -
> /* OFPT_ERROR: Error message (datapath -> controller). */
> struct ofp_error_msg {
> struct ofp_header header;
> diff --git a/lib/.gitignore b/lib/.gitignore
> index c5b6cac..6cbaf30 100644
> --- a/lib/.gitignore
> +++ b/lib/.gitignore
> @@ -3,4 +3,4 @@
> /dhparams.c
> /dirs.c
> /coverage-counters.c
> -/ofp-errors.c
> +/ofp-errors.inc
> diff --git a/lib/automake.mk b/lib/automake.mk
> index c0cc906..df27393 100644
> --- a/lib/automake.mk
> +++ b/lib/automake.mk
> @@ -277,13 +277,12 @@ lib/dirs.c: lib/dirs.c.in Makefile
> > lib/dirs.c.tmp
> mv lib/dirs.c.tmp lib/dirs.c
>
> -$(srcdir)/lib/ofp-errors.c: \
> - include/openflow/openflow.h include/openflow/nicira-ext.h \
> - build-aux/extract-ofp-errors
> - cd $(srcdir)/include && \
> - $(PYTHON) ../build-aux/extract-ofp-errors \
> - openflow/openflow.h openflow/nicira-ext.h > ../lib/ofp-errors.c
> -EXTRA_DIST += build-aux/extract-ofp-errors
> +$(srcdir)/lib/ofp-errors.inc: \
> + lib/ofp-errors.h $(srcdir)/build-aux/extract-ofp-errors
> + $(PYTHON) $(srcdir)/build-aux/extract-ofp-errors \
> + $(srcdir)/lib/ofp-errors.h > $@.tmp && mv $@.tmp $@
> +lib/ofp-errors.c: lib/ofp-errors.inc
> +EXTRA_DIST += build-aux/extract-ofp-errors lib/ofp-errors.inc
>
> INSTALL_DATA_LOCAL += lib-install-data-local
> lib-install-data-local:
> diff --git a/lib/autopath.c b/lib/autopath.c
> index 9a39c6a..321b106 100644
> --- a/lib/autopath.c
> +++ b/lib/autopath.c
> @@ -23,6 +23,7 @@
>
> #include "flow.h"
> #include "nx-match.h"
> +#include "ofp-errors.h"
> #include "ofp-util.h"
> #include "openflow/nicira-ext.h"
> #include "vlog.h"
> @@ -75,7 +76,7 @@ autopath_parse(struct nx_action_autopath *ap, const char *s_)
> free(s);
> }
>
> -int
> +enum ofperr
> autopath_check(const struct nx_action_autopath *ap, const struct flow *flow)
> {
> int n_bits = nxm_decode_n_bits(ap->ofs_nbits);
> @@ -84,7 +85,7 @@ autopath_check(const struct nx_action_autopath *ap, const struct flow *flow)
> if (n_bits < 16) {
> VLOG_WARN("at least 16 bit destination is required for autopath "
> "action.");
> - return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + return OFPERR_OFPBAC_BAD_ARGUMENT;
> }
>
> return nxm_dst_check(ap->dst, ofs, n_bits, flow);
> diff --git a/lib/autopath.h b/lib/autopath.h
> index 98b02b4..19e2d07 100644
> --- a/lib/autopath.h
> +++ b/lib/autopath.h
> @@ -18,6 +18,7 @@
> #define AUTOPATH_H 1
>
> #include <stdint.h>
> +#include "ofp-errors.h"
>
> struct flow;
> struct nx_action_autopath;
> @@ -29,6 +30,7 @@ struct nx_action_autopath;
> void autopath_execute(const struct nx_action_autopath *, struct flow *,
> uint16_t ofp_port);
> void autopath_parse(struct nx_action_autopath *, const char *);
> -int autopath_check(const struct nx_action_autopath *, const struct flow *);
> +enum ofperr autopath_check(const struct nx_action_autopath *,
> + const struct flow *);
>
> #endif /* autopath.h */
> diff --git a/lib/bundle.c b/lib/bundle.c
> index af1be63..600514f 100644
> --- a/lib/bundle.c
> +++ b/lib/bundle.c
> @@ -24,6 +24,7 @@
> #include "multipath.h"
> #include "nx-match.h"
> #include "ofpbuf.h"
> +#include "ofp-errors.h"
> #include "ofp-util.h"
> #include "openflow/nicira-ext.h"
> #include "vlog.h"
> @@ -100,8 +101,8 @@ bundle_execute_load(const struct nx_action_bundle *nab, struct flow *flow,
> /* Checks that 'nab' specifies a bundle action which is supported by this
> * bundle module. Uses the 'max_ports' parameter to validate each port using
> * ofputil_check_output_port(). Returns 0 if 'nab' is supported, otherwise an
> - * OpenFlow error code (as returned by ofp_mkerr()). */
> -int
> + * OFPERR_* error code. */
> +enum ofperr
> bundle_check(const struct nx_action_bundle *nab, int max_ports,
> const struct flow *flow)
> {
> @@ -109,7 +110,7 @@ bundle_check(const struct nx_action_bundle *nab, int max_ports,
> uint16_t n_slaves, fields, algorithm, subtype;
> uint32_t slave_type;
> size_t slaves_size, i;
> - int error;
> + enum ofperr error;
>
> subtype = ntohs(nab->subtype);
> n_slaves = ntohs(nab->n_slaves);
> @@ -118,7 +119,7 @@ bundle_check(const struct nx_action_bundle *nab, int max_ports,
> slave_type = ntohl(nab->slave_type);
> slaves_size = ntohs(nab->len) - sizeof *nab;
>
> - error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + error = OFPERR_OFPBAC_BAD_ARGUMENT;
> if (!flow_hash_fields_valid(fields)) {
> VLOG_WARN_RL(&rl, "unsupported fields %"PRIu16, fields);
> } else if (n_slaves > BUNDLE_MAX_SLAVES) {
> @@ -135,13 +136,13 @@ bundle_check(const struct nx_action_bundle *nab, int max_ports,
> for (i = 0; i < sizeof(nab->zero); i++) {
> if (nab->zero[i]) {
> VLOG_WARN_RL(&rl, "reserved field is nonzero");
> - error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + error = OFPERR_OFPBAC_BAD_ARGUMENT;
> }
> }
>
> if (subtype == NXAST_BUNDLE && (nab->ofs_nbits || nab->dst)) {
> VLOG_WARN_RL(&rl, "bundle action has nonzero reserved fields");
> - error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + error = OFPERR_OFPBAC_BAD_ARGUMENT;
> }
>
> if (subtype == NXAST_BUNDLE_LOAD) {
> @@ -151,7 +152,7 @@ bundle_check(const struct nx_action_bundle *nab, int max_ports,
> if (n_bits < 16) {
> VLOG_WARN_RL(&rl, "bundle_load action requires at least 16 bit "
> "destination.");
> - error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + error = OFPERR_OFPBAC_BAD_ARGUMENT;
> } else {
> error = nxm_dst_check(nab->dst, ofs, n_bits, flow) || error;
> }
> @@ -162,13 +163,14 @@ bundle_check(const struct nx_action_bundle *nab, int max_ports,
> "allocated for slaves. %zu bytes are required for "
> "%"PRIu16" slaves.", subtype, slaves_size,
> n_slaves * sizeof(ovs_be16), n_slaves);
> - error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
> + error = OFPERR_OFPBAC_BAD_LEN;
> }
>
> for (i = 0; i < n_slaves; i++) {
> uint16_t ofp_port = bundle_get_slave(nab, i);
> - int ofputil_error = ofputil_check_output_port(ofp_port, max_ports);
> + enum ofperr ofputil_error;
>
> + ofputil_error = ofputil_check_output_port(ofp_port, max_ports);
> if (ofputil_error) {
> VLOG_WARN_RL(&rl, "invalid slave %"PRIu16, ofp_port);
> error = ofputil_error;
> @@ -179,7 +181,7 @@ bundle_check(const struct nx_action_bundle *nab, int max_ports,
> * seem to be a real-world use-case for supporting it. */
> if (ofp_port == OFPP_CONTROLLER) {
> VLOG_WARN_RL(&rl, "unsupported controller slave");
> - error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT);
> + error = OFPERR_OFPBAC_BAD_OUT_PORT;
> }
> }
>
> diff --git a/lib/bundle.h b/lib/bundle.h
> index 12497f7..580ecf8 100644
> --- a/lib/bundle.h
> +++ b/lib/bundle.h
> @@ -21,6 +21,7 @@
> #include <stddef.h>
> #include <stdint.h>
>
> +#include "ofp-errors.h"
> #include "openflow/nicira-ext.h"
> #include "openvswitch/types.h"
>
> @@ -38,8 +39,8 @@ uint16_t bundle_execute(const struct nx_action_bundle *, const struct flow *,
> void bundle_execute_load(const struct nx_action_bundle *, struct flow *,
> bool (*slave_enabled)(uint16_t ofp_port, void *aux),
> void *aux);
> -int bundle_check(const struct nx_action_bundle *, int max_ports,
> - const struct flow *);
> +enum ofperr bundle_check(const struct nx_action_bundle *, int max_ports,
> + const struct flow *);
> void bundle_parse(struct ofpbuf *, const char *);
> void bundle_parse_load(struct ofpbuf *b, const char *);
> void bundle_format(const struct nx_action_bundle *, struct ds *);
> diff --git a/lib/dpif.c b/lib/dpif.c
> index 9cbf877..700b27a 100644
> --- a/lib/dpif.c
> +++ b/lib/dpif.c
> @@ -30,6 +30,7 @@
> #include "netdev.h"
> #include "netlink.h"
> #include "odp-util.h"
> +#include "ofp-errors.h"
> #include "ofp-print.h"
> #include "ofp-util.h"
> #include "ofpbuf.h"
> @@ -1201,13 +1202,12 @@ log_operation(const struct dpif *dpif, const char *operation, int error)
> {
> if (!error) {
> VLOG_DBG_RL(&dpmsg_rl, "%s: %s success", dpif_name(dpif), operation);
> - } else if (is_errno(error)) {
> + } else if (ofperr_is_valid(error)) {
> VLOG_WARN_RL(&error_rl, "%s: %s failed (%s)",
> - dpif_name(dpif), operation, strerror(error));
> + dpif_name(dpif), operation, ofperr_get_name(error));
> } else {
> - VLOG_WARN_RL(&error_rl, "%s: %s failed (%d/%d)",
> - dpif_name(dpif), operation,
> - get_ofp_err_type(error), get_ofp_err_code(error));
> + VLOG_WARN_RL(&error_rl, "%s: %s failed (%s)",
> + dpif_name(dpif), operation, strerror(error));
> }
> }
>
> diff --git a/lib/learn.c b/lib/learn.c
> index 9d97cb3..241f3d1 100644
> --- a/lib/learn.c
> +++ b/lib/learn.c
> @@ -22,6 +22,7 @@
> #include "dynamic-string.h"
> #include "meta-flow.h"
> #include "nx-match.h"
> +#include "ofp-errors.h"
> #include "ofp-util.h"
> #include "ofpbuf.h"
> #include "openflow/openflow.h"
> @@ -81,7 +82,7 @@ learn_min_len(uint16_t header)
> return min_len;
> }
>
> -static int
> +static enum ofperr
> learn_check_header(uint16_t header, size_t len)
> {
> int src_type = header & NX_LEARN_SRC_MASK;
> @@ -94,12 +95,12 @@ learn_check_header(uint16_t header, size_t len)
> src_type == NX_LEARN_SRC_FIELD)) {
> /* OK. */
> } else {
> - return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + return OFPERR_OFPBAC_BAD_ARGUMENT;
> }
>
> /* Check that the arguments don't overrun the end of the action. */
> if (len < learn_min_len(header)) {
> - return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
> + return OFPERR_OFPBAC_BAD_LEN;
> }
>
> return 0;
> @@ -107,7 +108,7 @@ learn_check_header(uint16_t header, size_t len)
>
> /* Checks that 'learn' (which must be at least 'sizeof *learn' bytes long) is a
> * valid action on 'flow'. */
> -int
> +enum ofperr
> learn_check(const struct nx_action_learn *learn, const struct flow *flow)
> {
> struct cls_rule rule;
> @@ -118,7 +119,7 @@ learn_check(const struct nx_action_learn *learn, const struct flow *flow)
> if (learn->flags & ~htons(OFPFF_SEND_FLOW_REM)
> || !is_all_zeros(learn->pad, sizeof learn->pad)
> || learn->table_id == 0xff) {
> - return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + return OFPERR_OFPBAC_BAD_ARGUMENT;
> }
>
> end = (char *) learn + ntohs(learn->len);
> @@ -128,8 +129,8 @@ learn_check(const struct nx_action_learn *learn, const struct flow *flow)
> int src_type = header & NX_LEARN_SRC_MASK;
> int dst_type = header & NX_LEARN_DST_MASK;
>
> + enum ofperr error;
> uint64_t value;
> - int error;
>
> if (!header) {
> break;
> @@ -158,7 +159,6 @@ learn_check(const struct nx_action_learn *learn, const struct flow *flow)
> if (dst_type == NX_LEARN_DST_MATCH || dst_type == NX_LEARN_DST_LOAD) {
> ovs_be32 dst_field = get_be32(&p);
> int dst_ofs = ntohs(get_be16(&p));
> - int error;
>
> error = (dst_type == NX_LEARN_DST_LOAD
> ? nxm_dst_check(dst_field, dst_ofs, n_bits, &rule.flow)
> @@ -175,7 +175,7 @@ learn_check(const struct nx_action_learn *learn, const struct flow *flow)
> }
> }
> if (!is_all_zeros(p, (char *) end - (char *) p)) {
> - return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + return OFPERR_OFPBAC_BAD_ARGUMENT;
> }
>
> return 0;
> @@ -412,9 +412,9 @@ learn_parse(struct ofpbuf *b, char *arg, const struct flow *flow)
> {
> char *orig = xstrdup(arg);
> char *name, *value;
> + enum ofperr error;
> size_t learn_ofs;
> size_t len;
> - int error;
>
> struct nx_action_learn *learn;
> struct cls_rule rule;
> @@ -512,8 +512,7 @@ learn_parse(struct ofpbuf *b, char *arg, const struct flow *flow)
> /* In theory the above should have caught any errors, but... */
> error = learn_check(learn, flow);
> if (error) {
> - char *msg = ofputil_error_to_string(error);
> - ovs_fatal(0, "%s: %s", orig, msg);
> + ovs_fatal(0, "%s: %s", orig, ofperr_to_string(error));
> }
> free(orig);
> }
> @@ -566,7 +565,7 @@ learn_format(const struct nx_action_learn *learn, struct ds *s)
> int dst_ofs;
> const struct mf_field *dst_field;
>
> - int error;
> + enum ofperr error;
> int i;
>
> if (!header) {
> @@ -574,11 +573,11 @@ learn_format(const struct nx_action_learn *learn, struct ds *s)
> }
>
> error = learn_check_header(header, (char *) end - (char *) p);
> - if (error == ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT)) {
> + if (error == OFPERR_OFPBAC_BAD_ARGUMENT) {
> ds_put_format(s, ",***bad flow_mod_spec header %"PRIx16"***)",
> header);
> return;
> - } else if (error == ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN)) {
> + } else if (error == OFPERR_OFPBAC_BAD_LEN) {
> ds_put_format(s, ",***flow_mod_spec at offset %td is %u bytes "
> "long but only %td bytes are left***)",
> (char *) p - (char *) (learn + 1) - 2,
> diff --git a/lib/learn.h b/lib/learn.h
> index 19a9089..b83bee2 100644
> --- a/lib/learn.h
> +++ b/lib/learn.h
> @@ -17,6 +17,8 @@
> #ifndef LEARN_H
> #define LEARN_H 1
>
> +#include "ofp-errors.h"
> +
> struct ds;
> struct flow;
> struct ofpbuf;
> @@ -28,7 +30,7 @@ struct nx_action_learn;
> * See include/openflow/nicira-ext.h for NXAST_LEARN specification.
> */
>
> -int learn_check(const struct nx_action_learn *, const struct flow *);
> +enum ofperr learn_check(const struct nx_action_learn *, const struct flow *);
> void learn_execute(const struct nx_action_learn *, const struct flow *,
> struct ofputil_flow_mod *);
>
> diff --git a/lib/learning-switch.c b/lib/learning-switch.c
> index ecc5509..c47fcb6 100644
> --- a/lib/learning-switch.c
> +++ b/lib/learning-switch.c
> @@ -29,6 +29,7 @@
> #include "hmap.h"
> #include "mac-learning.h"
> #include "ofpbuf.h"
> +#include "ofp-errors.h"
> #include "ofp-parse.h"
> #include "ofp-print.h"
> #include "ofp-util.h"
> diff --git a/lib/multipath.c b/lib/multipath.c
> index f68dafd..80d801d 100644
> --- a/lib/multipath.c
> +++ b/lib/multipath.c
> @@ -23,6 +23,7 @@
> #include <netinet/in.h>
> #include "dynamic-string.h"
> #include "nx-match.h"
> +#include "ofp-errors.h"
> #include "ofp-util.h"
> #include "openflow/nicira-ext.h"
> #include "packets.h"
> @@ -33,14 +34,14 @@ VLOG_DEFINE_THIS_MODULE(multipath);
> static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>
> /* multipath_check(). */
> -int
> +enum ofperr
> multipath_check(const struct nx_action_multipath *mp, const struct flow *flow)
> {
> uint32_t n_links = ntohs(mp->max_link) + 1;
> size_t min_n_bits = log_2_floor(n_links) + 1;
> int ofs = nxm_decode_ofs(mp->ofs_nbits);
> int n_bits = nxm_decode_n_bits(mp->ofs_nbits);
> - int error;
> + enum ofperr error;
>
> error = nxm_dst_check(mp->dst, ofs, n_bits, flow);
> if (error) {
> @@ -62,7 +63,7 @@ multipath_check(const struct nx_action_multipath *mp, const struct flow *flow)
> return 0;
> }
>
> - return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + return OFPERR_OFPBAC_BAD_ARGUMENT;
> }
>
> /* multipath_execute(). */
> diff --git a/lib/multipath.h b/lib/multipath.h
> index 8ac4bfd..3c4ff45 100644
> --- a/lib/multipath.h
> +++ b/lib/multipath.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2010 Nicira Networks.
> + * Copyright (c) 2010, 2011 Nicira Networks.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -18,6 +18,7 @@
> #define MULTIPATH_H 1
>
> #include <stdint.h>
> +#include "ofp-errors.h"
>
> struct ds;
> struct flow;
> @@ -29,7 +30,8 @@ struct nx_action_reg_move;
> * See include/openflow/nicira-ext.h for NXAST_MULTIPATH specification.
> */
>
> -int multipath_check(const struct nx_action_multipath *, const struct flow *);
> +enum ofperr multipath_check(const struct nx_action_multipath *,
> + const struct flow *);
> void multipath_execute(const struct nx_action_multipath *, struct flow *);
>
> void multipath_parse(struct nx_action_multipath *, const char *);
> diff --git a/lib/nx-match.c b/lib/nx-match.c
> index 9b3c1e0..e8aee53 100644
> --- a/lib/nx-match.c
> +++ b/lib/nx-match.c
> @@ -23,6 +23,7 @@
> #include "classifier.h"
> #include "dynamic-string.h"
> #include "meta-flow.h"
> +#include "ofp-errors.h"
> #include "ofp-util.h"
> #include "ofpbuf.h"
> #include "openflow/nicira-ext.h"
> @@ -36,16 +37,6 @@ VLOG_DEFINE_THIS_MODULE(nx_match);
> * peer and so there's not much point in showing a lot of them. */
> static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>
> -enum {
> - NXM_INVALID = OFP_MKERR_NICIRA(OFPET_BAD_REQUEST, NXBRC_NXM_INVALID),
> - NXM_BAD_TYPE = OFP_MKERR_NICIRA(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_TYPE),
> - NXM_BAD_VALUE = OFP_MKERR_NICIRA(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_VALUE),
> - NXM_BAD_MASK = OFP_MKERR_NICIRA(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_MASK),
> - NXM_BAD_PREREQ = OFP_MKERR_NICIRA(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_PREREQ),
> - NXM_DUP_TYPE = OFP_MKERR_NICIRA(OFPET_BAD_REQUEST, NXBRC_NXM_DUP_TYPE),
> - BAD_ARGUMENT = OFP_MKERR(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT)
> -};
> -
> /* Returns the width of the data for a field with the given 'header', in
> * bytes. */
> int
> @@ -96,7 +87,7 @@ nx_entry_ok(const void *p, unsigned int match_len)
> return header;
> }
>
> -int
> +enum ofperr
> nx_pull_match(struct ofpbuf *b, unsigned int match_len, uint16_t priority,
> struct cls_rule *rule)
> {
> @@ -108,29 +99,29 @@ nx_pull_match(struct ofpbuf *b, unsigned int match_len, uint16_t priority,
> VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a "
> "multiple of 8, is longer than space in message (max "
> "length %zu)", match_len, b->size);
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
>
> cls_rule_init_catchall(rule, priority);
> while ((header = nx_entry_ok(p, match_len)) != 0) {
> unsigned length = NXM_LENGTH(header);
> const struct mf_field *mf;
> - int error;
> + enum ofperr error;
>
> mf = mf_from_nxm_header(header);
> if (!mf) {
> - error = NXM_BAD_TYPE;
> + error = OFPERR_NXBRC_NXM_BAD_TYPE;
> } else if (!mf_are_prereqs_ok(mf, &rule->flow)) {
> - error = NXM_BAD_PREREQ;
> + error = OFPERR_NXBRC_NXM_BAD_PREREQ;
> } else if (!mf_is_all_wild(mf, &rule->wc)) {
> - error = NXM_DUP_TYPE;
> + error = OFPERR_NXBRC_NXM_DUP_TYPE;
> } else {
> unsigned int width = mf->n_bytes;
> union mf_value value;
>
> memcpy(&value, p + 4, width);
> if (!mf_is_value_valid(mf, &value)) {
> - error = NXM_BAD_VALUE;
> + error = OFPERR_NXBRC_NXM_BAD_VALUE;
> } else if (!NXM_HASMASK(header)) {
> error = 0;
> mf_set_value(mf, &value, rule);
> @@ -139,7 +130,7 @@ nx_pull_match(struct ofpbuf *b, unsigned int match_len, uint16_t priority,
>
> memcpy(&mask, p + 4 + width, width);
> if (!mf_is_mask_valid(mf, &mask)) {
> - error = NXM_BAD_MASK;
> + error = OFPERR_NXBRC_NXM_BAD_MASK;
> } else {
> error = 0;
> mf_set(mf, &value, &mask, rule);
> @@ -148,15 +139,12 @@ nx_pull_match(struct ofpbuf *b, unsigned int match_len, uint16_t priority,
> }
>
> if (error) {
> - char *msg = ofputil_error_to_string(error);
> VLOG_DBG_RL(&rl, "bad nxm_entry %#08"PRIx32" (vendor=%"PRIu32", "
> "field=%"PRIu32", hasmask=%"PRIu32", len=%"PRIu32"), "
> "(%s)", header,
> NXM_VENDOR(header), NXM_FIELD(header),
> NXM_HASMASK(header), NXM_LENGTH(header),
> - msg);
> - free(msg);
> -
> + ofperr_to_string(error));
> return error;
> }
>
> @@ -164,7 +152,7 @@ nx_pull_match(struct ofpbuf *b, unsigned int match_len, uint16_t priority,
> match_len -= 4 + length;
> }
>
> - return match_len ? NXM_INVALID : 0;
> + return match_len ? OFPERR_NXBRC_NXM_INVALID : 0;
> }
>
> /* nx_put_match() and helpers.
> @@ -918,7 +906,7 @@ nxm_check_reg_move(const struct nx_action_reg_move *action,
>
> /* Given a flow, checks that the source field represented by 'src_header'
> * in the range ['ofs', 'ofs' + 'n_bits') is valid. */
> -int
> +enum ofperr
> nxm_src_check(ovs_be32 src_header_, unsigned int ofs, unsigned int n_bits,
> const struct flow *flow)
> {
> @@ -933,12 +921,12 @@ nxm_src_check(ovs_be32 src_header_, unsigned int ofs, unsigned int n_bits,
> return 0;
> }
>
> - return BAD_ARGUMENT;
> + return OFPERR_OFPBAC_BAD_ARGUMENT;
> }
>
> /* Given a flow, checks that the destination field represented by 'dst_header'
> * in the range ['ofs', 'ofs' + 'n_bits') is valid. */
> -int
> +enum ofperr
> nxm_dst_check(ovs_be32 dst_header_, unsigned int ofs, unsigned int n_bits,
> const struct flow *flow)
> {
> @@ -955,16 +943,16 @@ nxm_dst_check(ovs_be32 dst_header_, unsigned int ofs, unsigned int n_bits,
> return 0;
> }
>
> - return BAD_ARGUMENT;
> + return OFPERR_OFPBAC_BAD_ARGUMENT;
> }
>
> -int
> +enum ofperr
> nxm_check_reg_load(const struct nx_action_reg_load *action,
> const struct flow *flow)
> {
> unsigned int ofs = nxm_decode_ofs(action->ofs_nbits);
> unsigned int n_bits = nxm_decode_n_bits(action->ofs_nbits);
> - int error;
> + enum ofperr error;
>
> error = nxm_dst_check(action->dst, ofs, n_bits, flow);
> if (error) {
> @@ -974,7 +962,7 @@ nxm_check_reg_load(const struct nx_action_reg_load *action,
> /* Reject 'action' if a bit numbered 'n_bits' or higher is set to 1 in
> * action->value. */
> if (n_bits < 64 && ntohll(action->value) >> n_bits) {
> - return BAD_ARGUMENT;
> + return OFPERR_OFPBAC_BAD_ARGUMENT;
> }
>
> return 0;
> diff --git a/lib/nx-match.h b/lib/nx-match.h
> index faeacd6..5ad1618 100644
> --- a/lib/nx-match.h
> +++ b/lib/nx-match.h
> @@ -21,6 +21,7 @@
> #include <sys/types.h>
> #include <netinet/in.h>
> #include "openvswitch/types.h"
> +#include "ofp-errors.h"
>
> struct cls_rule;
> struct ds;
> @@ -34,8 +35,8 @@ struct nx_action_reg_move;
> * See include/openflow/nicira-ext.h for NXM specification.
> */
>
> -int nx_pull_match(struct ofpbuf *, unsigned int match_len, uint16_t priority,
> - struct cls_rule *);
> +enum ofperr nx_pull_match(struct ofpbuf *, unsigned int match_len,
> + uint16_t priority, struct cls_rule *);
> int nx_put_match(struct ofpbuf *, const struct cls_rule *);
>
> char *nx_match_to_string(const uint8_t *, unsigned int match_len);
> @@ -51,11 +52,12 @@ void nxm_format_reg_move(const struct nx_action_reg_move *, struct ds *);
> void nxm_format_reg_load(const struct nx_action_reg_load *, struct ds *);
>
> int nxm_check_reg_move(const struct nx_action_reg_move *, const struct flow *);
> -int nxm_check_reg_load(const struct nx_action_reg_load *, const struct flow *);
> -int nxm_src_check(ovs_be32 src, unsigned int ofs, unsigned int n_bits,
> - const struct flow *);
> -int nxm_dst_check(ovs_be32 dst, unsigned int ofs, unsigned int n_bits,
> - const struct flow *);
> +enum ofperr nxm_check_reg_load(const struct nx_action_reg_load *,
> + const struct flow *);
> +enum ofperr nxm_src_check(ovs_be32 src, unsigned int ofs, unsigned int n_bits,
> + const struct flow *);
> +enum ofperr nxm_dst_check(ovs_be32 dst, unsigned int ofs, unsigned int n_bits,
> + const struct flow *);
>
> void nxm_execute_reg_move(const struct nx_action_reg_move *, struct flow *);
> void nxm_execute_reg_load(const struct nx_action_reg_load *, struct flow *);
> diff --git a/lib/ofp-errors.c b/lib/ofp-errors.c
> new file mode 100644
> index 0000000..785464e
> --- /dev/null
> +++ b/lib/ofp-errors.c
> @@ -0,0 +1,286 @@
> +#include <config.h>
> +#include "ofp-errors.h"
> +#include <errno.h>
> +#include "byte-order.h"
> +#include "dynamic-string.h"
> +#include "ofp-util.h"
> +#include "ofpbuf.h"
> +#include "openflow/openflow.h"
> +#include "vlog.h"
> +
> +VLOG_DEFINE_THIS_MODULE(ofp_errors);
> +
> +struct pair {
> + int type, code;
> +};
> +
> +#include "ofp-errors.inc"
> +
> +/* Returns an ofperr_domain that corresponds to the OpenFlow version number
> + * 'version' (one of the possible values of struct ofp_header's 'version'
> + * member). Returns NULL if the version isn't defined or isn't understood by
> + * OVS. */
> +const struct ofperr_domain *
> +ofperr_domain_from_version(uint8_t version)
> +{
> + return (version == ofperr_of10.version ? &ofperr_of10
> + : version == ofperr_of11.version ? &ofperr_of11
> + : NULL);
> +}
> +
> +/* Returns true if 'error' is a valid OFPERR_* value, false otherwise. */
> +bool
> +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
> +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));
> +}
> +
> +/* Returns true if 'error' can be encoded as an OpenFlow error message in
> + * 'domain', false otherwise.
> + *
> + * A given error may not be encodable in some domains because each OpenFlow
> + * version tends to introduce new errors and retire some old ones. */
> +bool
> +ofperr_is_encodable(enum ofperr error, const struct ofperr_domain *domain)
> +{
> + return (ofperr_is_valid(error)
> + && domain->errors[error - OFPERR_OFS].code >= 0);
> +}
> +
> +/* Returns the OFPERR_* value that corresponds to 'type' and 'code' within
> + * 'domain', or 0 if no such OFPERR_* value exists. */
> +enum ofperr
> +ofperr_decode(const struct ofperr_domain *domain, uint16_t type, uint16_t code)
> +{
> + return domain->decode(type, code);
> +}
> +
> +/* Returns the OFPERR_* value that corresponds to the category 'type' within
> + * 'domain', or 0 if no such OFPERR_* value exists. */
> +enum ofperr
> +ofperr_decode_type(const struct ofperr_domain *domain, uint16_t type)
> +{
> + return domain->decode_type(type);
> +}
> +
> +/* 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.
> + *
> + * Consider ofperr_to_string() instead, if the error code might be an errno
> + * value. */
> +const char *
> +ofperr_get_name(enum ofperr error)
> +{
> + return (ofperr_is_valid(error)
> + ? error_names[error - OFPERR_OFS]
> + : "<invalid>");
> +}
> +
> +/* Returns an extended description name of 'error', e.g. "ofp_header.type not
> + * supported." if 'error' is OFPBRC_BAD_TYPE, or "<invalid>" if 'error' is not
> + * a valid OFPERR_* value. */
> +const char *
> +ofperr_get_description(enum ofperr error)
> +{
> + return (ofperr_is_valid(error)
> + ? error_comments[error - OFPERR_OFS]
> + : "<invalid>");
> +}
> +
> +static struct ofpbuf *
> +ofperr_encode_msg__(enum ofperr error, const struct ofperr_domain *domain,
> + ovs_be32 xid, const void *data, size_t data_len)
> +{
> + struct ofp_error_msg *oem;
> + const struct pair *pair;
> + struct ofpbuf *buf;
> +
> + if (!domain) {
> + return NULL;
> + }
> +
> + if (!ofperr_is_encodable(error, domain)) {
> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> +
> + 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));
> + } 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);
> + }
> + }
> +
> + return NULL;
> + }
> +
> + pair = &domain->errors[MIN(error - OFPERR_OFS, OFPERR_N_ERRORS)];
> + if (!ofperr_is_nx_extension(error)) {
> + oem = make_openflow_xid(data_len + sizeof *oem, OFPT_ERROR, xid, &buf);
> + oem->type = htons(pair->type);
> + oem->code = htons(pair->code);
> + } else {
> + struct nx_vendor_error *nve;
> +
> + oem = make_openflow_xid(data_len + sizeof *oem + sizeof *nve,
> + OFPT_ERROR, xid, &buf);
> + oem->type = htons(NXET_VENDOR);
> + oem->code = htons(NXVC_VENDOR_ERROR);
> +
> + nve = (struct nx_vendor_error *)oem->data;
> + nve->vendor = htonl(NX_VENDOR_ID);
> + nve->type = htons(pair->type);
> + nve->code = htons(pair->code);
> + }
> + oem->header.version = domain->version;
> +
> + buf->size -= data_len;
> + ofpbuf_put(buf, data, data_len);
> +
> + return buf;
> +}
> +
> +/* Creates and returns an OpenFlow message of type OFPT_ERROR that conveys the
> + * given 'error'.
> + *
> + * 'oh->version' determines the OpenFlow version of the error reply.
> + * 'oh->xid' determines the xid of the error reply.
> + * The error reply will contain an initial subsequence of 'oh', up to
> + * 'oh->length' or 64 bytes, whichever is shorter.
> + *
> + * Returns NULL if 'error' is not an OpenFlow error code or if 'error' cannot
> + * be encoded as OpenFlow version 'oh->version'.
> + *
> + * This function isn't appropriate for encoding OFPET_HELLO_FAILED error
> + * messages. Use ofperr_encode_hello() instead. */
> +struct ofpbuf *
> +ofperr_encode_reply(enum ofperr error, const struct ofp_header *oh)
> +{
> + const struct ofperr_domain *domain;
> + uint16_t len = ntohs(oh->length);
> +
> + domain = ofperr_domain_from_version(oh->version);
> + return ofperr_encode_msg__(error, domain, oh->xid, oh, MIN(len, 64));
> +}
> +
> +/* Creates and returns an OpenFlow message of type OFPT_ERROR that conveys the
> + * given 'error', in the error domain 'domain'. The error message will include
> + * the additional null-terminated text string 's'.
> + *
> + * If 'domain' is NULL, uses the OpenFlow 1.0 error domain. OFPET_HELLO_FAILED
> + * error messages are supposed to be backward-compatible, so in theory this
> + * should work.
> + *
> + * Returns NULL if 'error' is not an OpenFlow error code or if 'error' cannot
> + * be encoded in 'domain'. */
> +struct ofpbuf *
> +ofperr_encode_hello(enum ofperr error, const struct ofperr_domain *domain,
> + const char *s)
> +{
> + if (!domain) {
> + domain = &ofperr_of10;
> + }
> + return ofperr_encode_msg__(error, domain, htonl(0), s, strlen(s));
> +}
> +
> +/* Tries to decodes 'oh', which should be an OpenFlow OFPT_ERROR message.
> + * Returns an OFPERR_* constant on success, 0 on failure.
> + *
> + * If 'payload_ofs' is nonnull, on success '*payload_ofs' is set to the offset
> + * to the payload starting from 'oh' and on failure it is set to 0. */
> +enum ofperr
> +ofperr_decode_msg(const struct ofp_header *oh, size_t *payload_ofs)
> +{
> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> +
> + const struct ofperr_domain *domain;
> + const struct ofp_error_msg *oem;
> + uint16_t type, code;
> + enum ofperr error;
> + struct ofpbuf b;
> +
> + if (payload_ofs) {
> + *payload_ofs = 0;
> + }
> +
> + /* Pull off the error message. */
> + ofpbuf_use_const(&b, oh, ntohs(oh->length));
> + oem = ofpbuf_try_pull(&b, sizeof *oem);
> + if (!oem) {
> + return 0;
> + }
> +
> + /* Check message type and version. */
> + if (oh->type != OFPT_ERROR) {
> + return 0;
> + }
> + domain = ofperr_domain_from_version(oh->version);
> + if (!domain) {
> + return 0;
> + }
> +
> + /* Get the error type and code. */
> + type = ntohs(oem->type);
> + code = ntohs(oem->code);
> + if (type == NXET_VENDOR && code == NXVC_VENDOR_ERROR) {
> + const struct nx_vendor_error *nve = ofpbuf_try_pull(&b, sizeof *nve);
> + if (!nve) {
> + return 0;
> + }
> +
> + if (nve->vendor != htonl(NX_VENDOR_ID)) {
> + VLOG_WARN_RL(&rl, "error contains unknown vendor ID %#"PRIx32,
> + ntohl(nve->vendor));
> + return 0;
> + }
> + type = ntohs(nve->type);
> + 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. */
> + error = ofperr_decode(domain, type, code);
> + if (!error) {
> + error = ofperr_decode_type(domain, type);
> + }
> + if (error && payload_ofs) {
> + *payload_ofs = (uint8_t *) b.data - (uint8_t *) oh;
> + }
> + return error;
> +}
> +
> +/* If 'error' is a valid OFPERR_* value, returns its name
> + * (e.g. "OFPBRC_BAD_TYPE" for OFPBRC_BAD_TYPE). Otherwise, assumes that
> + * 'error' is a positive errno value and returns what strerror() produces for
> + * 'error'. */
> +const char *
> +ofperr_to_string(enum ofperr error)
> +{
> + return ofperr_is_valid(error) ? ofperr_get_name(error) : strerror(error);
> +}
> +
> diff --git a/lib/ofp-errors.h b/lib/ofp-errors.h
> index d677b5d..fbd28e3 100644
> --- a/lib/ofp-errors.h
> +++ b/lib/ofp-errors.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2008, 2009, 2010 Nicira Networks.
> + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -17,12 +17,389 @@
> #ifndef OFP_ERRORS_H
> #define OFP_ERRORS_H 1
>
> +#include <stdbool.h>
> +#include <stddef.h>
> #include <stdint.h>
>
> -/* These functions are building blocks for the ofputil_format_error() and
> - * ofputil_error_to_string() functions declared in ofp-util.h. Those functions
> - * have friendlier interfaces and should usually be preferred. */
> -const char *ofp_error_type_to_string(uint16_t value);
> -const char *ofp_error_code_to_string(uint16_t type, uint16_t code);
> +struct ds;
> +struct ofp_header;
> +
> +/* Error codes.
> + *
> + * We embed system errno values and OpenFlow standard and vendor extension
> + * error codes into the positive range of "int":
> + *
> + * - Errno values are assumed to use the range 1 through 2**30 - 1.
> + *
> + * (C and POSIX say that errno values are positive. We assume that they
> + * are less than 2**29. They are actually less than 65536 on at least
> + * Linux, FreeBSD, OpenBSD, and Windows.)
> + *
> + * - OpenFlow standard and vendor extension error codes use the range
> + * starting at 2**30 (OFPERR_OFS).
> + *
> + * Zero and negative values are not used.
> + */
> +
> +#define OFPERR_OFS (1 << 30)
> +
> +enum ofperr {
> +/* ## ------------------ ## */
> +/* ## OFPET_HELLO_FAILED ## */
> +/* ## ------------------ ## */
> +
> + /* OF(0). Hello protocol failed. */
> + OFPERR_OFPET_HELLO_FAILED = OFPERR_OFS,
> +
> + /* OF(0,0). No compatible version. */
> + OFPERR_OFPHFC_INCOMPATIBLE,
> +
> + /* OF(0,1). Permissions error. */
> + OFPERR_OFPHFC_EPERM,
> +
> +/* ## ----------------- ## */
> +/* ## OFPET_BAD_REQUEST ## */
> +/* ## ----------------- ## */
> +
> + /* OF(1). Request was not understood. */
> + OFPERR_OFPET_BAD_REQUEST,
> +
> + /* OF(1,0). ofp_header.version not supported. */
> + OFPERR_OFPBRC_BAD_VERSION,
> +
> + /* OF(1,1). ofp_header.type not supported. */
> + OFPERR_OFPBRC_BAD_TYPE,
> +
> + /* OF(1,2). ofp_stats_msg.type not supported. */
> + OFPERR_OFPBRC_BAD_STAT,
> +
> + /* OF(1,3). Vendor not supported (in ofp_vendor_header or
> + * ofp_stats_msg). */
> + OFPERR_OFPBRC_BAD_VENDOR,
> +
> + /* OF(1,4). Vendor subtype not supported. */
> + OFPERR_OFPBRC_BAD_SUBTYPE,
> +
> + /* OF(1,5). Permissions error. */
> + OFPERR_OFPBRC_EPERM,
> +
> + /* OF(1,6). Wrong request length for type. */
> + OFPERR_OFPBRC_BAD_LEN,
> +
> + /* OF(1,7). Specified buffer has already been used. */
> + OFPERR_OFPBRC_BUFFER_EMPTY,
> +
> + /* OF(1,8). Specified buffer does not exist. */
> + OFPERR_OFPBRC_BUFFER_UNKNOWN,
> +
> + /* OF1.1(1,9). Specified table-id invalid or does not exist. */
> + OFPERR_OFPBRC_BAD_TABLE_ID,
> +
> + /* NX(1,256). Invalid NXM flow match. */
> + OFPERR_NXBRC_NXM_INVALID,
> +
> + /* NX(1,257). The nxm_type, or nxm_type taken in combination with
> + * nxm_hasmask or nxm_length or both, is invalid or not implemented. */
> + OFPERR_NXBRC_NXM_BAD_TYPE,
> +
> + /* NX(1,258). Invalid nxm_value. */
> + OFPERR_NXBRC_NXM_BAD_VALUE,
> +
> + /* NX(1,259). Invalid nxm_mask. */
> + OFPERR_NXBRC_NXM_BAD_MASK,
> +
> + /* NX(1,260). A prerequisite was not met. */
> + OFPERR_NXBRC_NXM_BAD_PREREQ,
> +
> + /* NX(1,261). A given nxm_type was specified more than once. */
> + OFPERR_NXBRC_NXM_DUP_TYPE,
> +
> + /* NX(1,512). A request specified a nonexistent table ID. */
> + OFPERR_NXBRC_BAD_TABLE_ID,
> +
> + /* NX(1,513). NXT_ROLE_REQUEST specified an invalid role. */
> + OFPERR_NXBRC_BAD_ROLE,
> +
> + /* NX(1,514). The in_port in an ofp_packet_out request is invalid. */
> + OFPERR_NXBRC_BAD_IN_PORT,
> +
> +/* ## ---------------- ## */
> +/* ## OFPET_BAD_ACTION ## */
> +/* ## ---------------- ## */
> +
> + /* OF(2). Error in action description. */
> + OFPERR_OFPET_BAD_ACTION,
> +
> + /* OF(2,0). Unknown action type. */
> + OFPERR_OFPBAC_BAD_TYPE,
> +
> + /* OF(2,1). Length problem in actions. */
> + OFPERR_OFPBAC_BAD_LEN,
> +
> + /* OF(2,2). Unknown experimenter id specified. */
> + OFPERR_OFPBAC_BAD_VENDOR,
> +
> + /* OF(2,3). Unknown action type for experimenter id. */
> + OFPERR_OFPBAC_BAD_VENDOR_TYPE,
> +
> + /* OF(2,4). Problem validating output port. */
> + OFPERR_OFPBAC_BAD_OUT_PORT,
> +
> + /* OF(2,5). Bad action argument. */
> + OFPERR_OFPBAC_BAD_ARGUMENT,
> +
> + /* OF(2,6). Permissions error. */
> + OFPERR_OFPBAC_EPERM,
> +
> + /* OF(2,7). Can't handle this many actions. */
> + OFPERR_OFPBAC_TOO_MANY,
> +
> + /* OF(2,8). Problem validating output queue. */
> + OFPERR_OFPBAC_BAD_QUEUE,
> +
> + /* OF1.1(2,9). Invalid group id in forward action. */
> + OFPERR_OFPBAC_BAD_OUT_GROUP,
> +
> + /* OF1.1(2,10). Action can't apply for this match. */
> + OFPERR_OFPBAC_MATCH_INCONSISTENT,
> +
> + /* OF1.1(2,11). Action order is unsupported for the action list in an
> + * Apply-Actions instruction */
> + OFPERR_OFPBAC_UNSUPPORTED_ORDER,
> +
> + /* OF1.1(2,12). Actions uses an unsupported tag/encap. */
> + OFPERR_OFPBAC_BAD_TAG,
> +
> +/* ## --------------------- ## */
> +/* ## OFPET_BAD_INSTRUCTION ## */
> +/* ## --------------------- ## */
> +
> + /* OF1.1(3). Error in instruction list. */
> + OFPERR_OFPET_BAD_INSTRUCTION,
> +
> + /* OF1.1(3,0). Unknown instruction. */
> + OFPERR_OFPBIC_UNKNOWN_INST,
> +
> + /* OF1.1(3,1). Switch or table does not support the instruction. */
> + OFPERR_OFPBIC_UNSUP_INST,
> +
> + /* OF1.1(3,2). Invalid Table-ID specified. */
> + OFPERR_OFPBIC_BAD_TABLE_ID,
> +
> + /* OF1.1(3,3). Metadata value unsupported by datapath. */
> + OFPERR_OFPBIC_UNSUP_METADATA,
> +
> + /* OF1.1(3,4). Metadata mask value unsupported by datapath. */
> + OFPERR_OFPBIC_UNSUP_METADATA_MASK,
> +
> + /* OF1.1(3,5). Specific experimenter instruction unsupported. */
> + OFPERR_OFPBIC_UNSUP_EXP_INST,
> +
> +/* ## --------------- ## */
> +/* ## 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,
> +
> + /* OF1.1(4,1). Length problem in match. */
> + OFPERR_OFPBMC_BAD_LEN,
> +
> + /* OF1.1(4,2). Match uses an unsupported tag/encap. */
> + OFPERR_OFPBMC_BAD_TAG,
> +
> + /* OF1.1(4,3). Unsupported datalink addr mask - switch does not support
> + * arbitrary datalink address mask. */
> + OFPERR_OFPBMC_BAD_DL_ADDR_MASK,
> +
> + /* OF1.1(4,4). Unsupported network addr mask - switch does not support
> + * arbitrary network address mask. */
> + OFPERR_OFPBMC_BAD_NW_ADDR_MASK,
> +
> + /* OF1.1(4,5). Unsupported wildcard specified in the match. */
> + OFPERR_OFPBMC_BAD_WILDCARDS,
> +
> + /* OF1.1(4,6). Unsupported field in the match. */
> + OFPERR_OFPBMC_BAD_FIELD,
> +
> + /* OF1.1(4,7). Unsupported value in a match field. */
> + OFPERR_OFPBMC_BAD_VALUE,
> +
> +/* ## --------------------- ## */
> +/* ## 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,
> +
> + /* OF1.0(3,0). Flow not added because of full tables. */
> + OFPERR_OFPFMFC_ALL_TABLES_FULL,
> +
> + /* OF1.1(5,1). Flow not added because table was full. */
> + OFPERR_OFPFMFC_TABLE_FULL,
> +
> + /* OF1.1(5,2). Table does not exist */
> + OFPERR_OFPFMFC_BAD_TABLE_ID,
> +
> + /* OF1.0(3,1), OF1.1(5,3). Attempted to add overlapping flow with
> + * CHECK_OVERLAP flag set. */
> + OFPERR_OFPFMFC_OVERLAP,
> +
> + /* OF1.0(3,2), OF1.1(5,4). Permissions error. */
> + OFPERR_OFPFMFC_EPERM,
> +
> + /* OF1.1(5,5). Flow not added because of unsupported idle/hard timeout. */
> + OFPERR_OFPFMFC_BAD_TIMEOUT,
> +
> + /* OF1.0(3,3). Flow not added because of non-zero idle/hard timeout. */
> + OFPERR_OFPFMFC_BAD_EMERG_TIMEOUT,
> +
> + /* OF1.0(3,4), OF1.1(5,6). Unsupported or unknown command. */
> + OFPERR_OFPFMFC_BAD_COMMAND,
> +
> + /* OF1.0(3,5). Unsupported action list - cannot process in the order
> + * specified. */
> + OFPERR_OFPFMFC_UNSUPPORTED,
> +
> + /* NX1.0(3,256), NX1.1(5,256). Generic hardware error. */
> + OFPERR_NXFMFC_HARDWARE,
> +
> + /* NX1.0(3,257), NX1.1(5,257). A nonexistent table ID was specified in the
> + * "command" field of struct ofp_flow_mod, when the nxt_flow_mod_table_id
> + * extension is enabled. */
> + OFPERR_NXFMFC_BAD_TABLE_ID,
> +
> +/* ## ---------------------- ## */
> +/* ## 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,
> +
> + /* OF1.1(6,1). Group not added because Group specified is invalid. */
> + OFPERR_OFPGMFC_INVALID_GROUP,
> +
> + /* OF1.1(6,2). Switch does not support unequal load sharing with select
> + * groups. */
> + OFPERR_OFPGMFC_WEIGHT_UNSUPPORTED,
> +
> + /* OF1.1(6,3). The group table is full. */
> + OFPERR_OFPGMFC_OUT_OF_GROUPS,
> +
> + /* OF1.1(6,4). The maximum number of action buckets for a group has been
> + * exceeded. */
> + OFPERR_OFPGMFC_OUT_OF_BUCKETS,
> +
> + /* OF1.1(6,5). Switch does not support groups that forward to groups. */
> + OFPERR_OFPGMFC_CHAINING_UNSUPPORTED,
> +
> + /* OF1.1(6,6). This group cannot watch the watch_port or watch_group
> + * specified. */
> + OFPERR_OFPGMFC_WATCH_UNSUPPORTED,
> +
> + /* OF1.1(6,7). Group entry would cause a loop. */
> + OFPERR_OFPGMFC_LOOP,
> +
> + /* OF1.1(6,8). Group not modified because a group MODIFY attempted to
> + * modify a non-existent group. */
> + OFPERR_OFPGMFC_UNKNOWN_GROUP,
> +
> +/* ## --------------------- ## */
> +/* ## 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,
> +
> + /* OF1.0(4,1), OF1.1(7,1). Specified hardware address does not match the
> + * port number. */
> + OFPERR_OFPPMFC_BAD_HW_ADDR,
> +
> + /* OF1.1(7,2). Specified config is invalid. */
> + OFPERR_OFPPMFC_BAD_CONFIG,
> +
> + /* OF1.1(7,3). Specified advertise is invalid. */
> + OFPERR_OFPPMFC_BAD_ADVERTISE,
> +
> +/* ## ---------------------- ## */
> +/* ## 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,
> +
> + /* OF1.1(8,1). Specified config is invalid. */
> + OFPERR_OFPTMFC_BAD_CONFIG,
> +
> +/* ## --------------------- ## */
> +/* ## 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,
> +
> + /* OF1.0(5,1), OF1.1(9,1). Queue does not exist. */
> + OFPERR_OFPQOFC_BAD_QUEUE,
> +
> + /* OF1.0(5,2), OF1.1(9,2). Permissions error. */
> + OFPERR_OFPQOFC_EPERM,
> +
> +/* ## -------------------------- ## */
> +/* ## 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,
> +
> + /* OF1.1(10,1). Specified len is invalid. */
> + OFPERR_OFPSCFC_BAD_LEN,
> +};
> +
> +extern const struct ofperr_domain ofperr_of10;
> +extern const struct ofperr_domain ofperr_of11;
> +
> +const struct ofperr_domain *ofperr_domain_from_version(uint8_t 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, const struct ofperr_domain *);
> +
> +enum ofperr ofperr_decode(const struct ofperr_domain *,
> + uint16_t type, uint16_t code);
> +enum ofperr ofperr_decode_type(const struct ofperr_domain *, uint16_t type);
> +
> +enum ofperr ofperr_decode_msg(const struct ofp_header *, size_t *payload_ofs);
> +struct ofpbuf *ofperr_encode_reply(enum ofperr, const struct ofp_header *);
> +struct ofpbuf *ofperr_encode_hello(enum ofperr, const struct ofperr_domain *,
> + const char *);
> +
> +const char *ofperr_get_name(enum ofperr);
> +const char *ofperr_get_description(enum ofperr);
> +
> +void ofperr_format(struct ds *, enum ofperr);
> +const char *ofperr_to_string(enum ofperr);
>
> #endif /* ofp-errors.h */
> diff --git a/lib/ofp-print.c b/lib/ofp-print.c
> index 67f5883..632766c 100644
> --- a/lib/ofp-print.c
> +++ b/lib/ofp-print.c
> @@ -34,6 +34,7 @@
> #include "learn.h"
> #include "multipath.h"
> #include "nx-match.h"
> +#include "ofp-errors.h"
> #include "ofp-util.h"
> #include "ofpbuf.h"
> #include "openflow/openflow.h"
> @@ -45,7 +46,7 @@
> #include "util.h"
>
> static void ofp_print_queue_name(struct ds *string, uint32_t port);
> -static void ofp_print_error(struct ds *, int error);
> +static void ofp_print_error(struct ds *, enum ofperr);
>
>
> /* Returns a string that represents the contents of the Ethernet frame in the
> @@ -752,7 +753,7 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh,
> {
> struct ofputil_flow_mod fm;
> bool need_priority;
> - int error;
> + enum ofperr error;
>
> error = ofputil_decode_flow_mod(&fm, oh, true);
> if (error) {
> @@ -851,7 +852,7 @@ static void
> ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh)
> {
> struct ofputil_flow_removed fr;
> - int error;
> + enum ofperr error;
>
> error = ofputil_decode_flow_removed(&fr, oh);
> if (error) {
> @@ -902,14 +903,12 @@ ofp_print_port_mod(struct ds *string, const struct ofp_port_mod *opm)
> }
>
> static void
> -ofp_print_error(struct ds *string, int error)
> +ofp_print_error(struct ds *string, enum ofperr error)
> {
> if (string->length) {
> ds_put_char(string, ' ');
> }
> - ds_put_cstr(string, "***decode error: ");
> - ofputil_format_error(string, error);
> - ds_put_cstr(string, "***\n");
> + ds_put_format(string, "***decode error: %s***\n", ofperr_get_name(error));
> }
>
> static void
> @@ -918,32 +917,26 @@ ofp_print_error_msg(struct ds *string, const struct ofp_error_msg *oem)
> size_t len = ntohs(oem->header.length);
> size_t payload_ofs, payload_len;
> const void *payload;
> - int error;
> + enum ofperr error;
> char *s;
>
> - error = ofputil_decode_error_msg(&oem->header, &payload_ofs);
> - if (!is_ofp_error(error)) {
> - ofp_print_error(string, error);
> + error = ofperr_decode_msg(&oem->header, &payload_ofs);
> + if (!error) {
> + ds_put_cstr(string, "***decode error***");
> ds_put_hex_dump(string, oem->data, len - sizeof *oem, 0, true);
> return;
> }
>
> - ds_put_char(string, ' ');
> - ofputil_format_error(string, error);
> - ds_put_char(string, '\n');
> + ds_put_format(string, " %s\n", ofperr_get_name(error));
>
> payload = (const uint8_t *) oem + payload_ofs;
> payload_len = len - payload_ofs;
> - switch (get_ofp_err_type(error)) {
> - case OFPET_HELLO_FAILED:
> + if (error == OFPERR_OFPHFC_INCOMPATIBLE || error == OFPERR_OFPHFC_EPERM) {
> ds_put_printable(string, payload, payload_len);
> - break;
> -
> - default:
> + } else {
> s = ofp_to_string(payload, payload_len, 1);
> ds_put_cstr(string, s);
> free(s);
> - break;
> }
> }
>
> @@ -982,7 +975,7 @@ ofp_print_flow_stats_request(struct ds *string,
> const struct ofp_stats_msg *osm)
> {
> struct ofputil_flow_stats_request fsr;
> - int error;
> + enum ofperr error;
>
> error = ofputil_decode_flow_stats_request(&fsr, &osm->header);
> if (error) {
> @@ -1454,9 +1447,6 @@ ofp_to_string(const void *oh_, size_t len, int verbosity)
> } else if (len < sizeof(struct ofp_header)) {
> ds_put_format(&string, "OpenFlow packet too short (only %zu bytes):\n",
> len);
> - } else if (oh->version != OFP_VERSION) {
> - ds_put_format(&string, "Bad OpenFlow version %"PRIu8":\n",
> - oh->version);
> } else if (ntohs(oh->length) > len) {
> ds_put_format(&string,
> "(***truncated to %zu bytes from %"PRIu16"***)\n",
> @@ -1467,7 +1457,7 @@ ofp_to_string(const void *oh_, size_t len, int verbosity)
> ntohs(oh->length), len);
> } else {
> const struct ofputil_msg_type *type;
> - int error;
> + enum ofperr error;
>
> error = ofputil_decode_msg_type(oh, &type);
> if (!error) {
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index ec0e864..cba4f32 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -289,10 +289,10 @@ 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. */
> + enum ofperr missing_error; /* Error value for missing type. */
> };
>
> -static int
> +static enum ofperr
> ofputil_check_length(const struct ofputil_msg_type *type, unsigned int size)
> {
> switch (type->extra_multiple) {
> @@ -301,7 +301,7 @@ ofputil_check_length(const struct ofputil_msg_type *type, unsigned int size)
> VLOG_WARN_RL(&bad_ofmsg_rl, "received %s with incorrect "
> "length %u (expected length %u)",
> type->name, size, type->min_size);
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
> return 0;
>
> @@ -310,7 +310,7 @@ ofputil_check_length(const struct ofputil_msg_type *type, unsigned int size)
> VLOG_WARN_RL(&bad_ofmsg_rl, "received %s with incorrect "
> "length %u (expected length at least %u bytes)",
> type->name, size, type->min_size);
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
> return 0;
>
> @@ -322,13 +322,13 @@ ofputil_check_length(const struct ofputil_msg_type *type, unsigned int size)
> "by an integer multiple of %u bytes)",
> type->name, size,
> type->min_size, type->extra_multiple);
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
> return 0;
> }
> }
>
> -static int
> +static enum ofperr
> ofputil_lookup_openflow_message(const struct ofputil_msg_category *cat,
> uint8_t version, uint32_t value,
> const struct ofputil_msg_type **typep)
> @@ -348,7 +348,7 @@ ofputil_lookup_openflow_message(const struct ofputil_msg_category *cat,
> return cat->missing_error;
> }
>
> -static int
> +static enum ofperr
> ofputil_decode_vendor(const struct ofp_header *oh, size_t length,
> const struct ofputil_msg_type **typep)
> {
> @@ -381,7 +381,7 @@ ofputil_decode_vendor(const struct ofp_header *oh, size_t length,
> 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)
> + OFPERR_OFPBRC_BAD_SUBTYPE
> };
>
> const struct ofp_vendor_header *ovh;
> @@ -391,14 +391,14 @@ ofputil_decode_vendor(const struct ofp_header *oh, size_t length,
> if (length == ntohs(oh->length)) {
> VLOG_WARN_RL(&bad_ofmsg_rl, "truncated vendor message");
> }
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
>
> ovh = (const struct ofp_vendor_header *) oh;
> if (ovh->vendor != htonl(NX_VENDOR_ID)) {
> VLOG_WARN_RL(&bad_ofmsg_rl, "received vendor message for unknown "
> "vendor %"PRIx32, ntohl(ovh->vendor));
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR);
> + return OFPERR_OFPBRC_BAD_VENDOR;
> }
>
> if (length < sizeof(struct nicira_header)) {
> @@ -408,7 +408,7 @@ ofputil_decode_vendor(const struct ofp_header *oh, size_t length,
> ntohs(ovh->header.length),
> sizeof(struct nicira_header));
> }
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
>
> nh = (const struct nicira_header *) oh;
> @@ -416,7 +416,7 @@ ofputil_decode_vendor(const struct ofp_header *oh, size_t length,
> ntohl(nh->subtype), typep);
> }
>
> -static int
> +static enum ofperr
> check_nxstats_msg(const struct ofp_header *oh, size_t length)
> {
> const struct ofp_stats_msg *osm = (const struct ofp_stats_msg *) oh;
> @@ -426,27 +426,27 @@ check_nxstats_msg(const struct ofp_header *oh, size_t length)
> if (length == ntohs(oh->length)) {
> VLOG_WARN_RL(&bad_ofmsg_rl, "truncated vendor stats message");
> }
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
>
> memcpy(&vendor, osm + 1, sizeof vendor);
> if (vendor != htonl(NX_VENDOR_ID)) {
> VLOG_WARN_RL(&bad_ofmsg_rl, "received vendor stats message for "
> "unknown vendor %"PRIx32, ntohl(vendor));
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR);
> + return OFPERR_OFPBRC_BAD_VENDOR;
> }
>
> if (length < sizeof(struct nicira_stats_msg)) {
> if (length == ntohs(osm->header.length)) {
> VLOG_WARN_RL(&bad_ofmsg_rl, "truncated Nicira stats message");
> }
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
>
> return 0;
> }
>
> -static int
> +static enum ofperr
> ofputil_decode_nxst_request(const struct ofp_header *oh, size_t length,
> const struct ofputil_msg_type **typep)
> {
> @@ -463,11 +463,11 @@ ofputil_decode_nxst_request(const struct ofp_header *oh, size_t length,
> 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)
> + OFPERR_OFPBRC_BAD_SUBTYPE
> };
>
> const struct nicira_stats_msg *nsm;
> - int error;
> + enum ofperr error;
>
> error = check_nxstats_msg(oh, length);
> if (error) {
> @@ -479,7 +479,7 @@ ofputil_decode_nxst_request(const struct ofp_header *oh, size_t length,
> ntohl(nsm->subtype), typep);
> }
>
> -static int
> +static enum ofperr
> ofputil_decode_nxst_reply(const struct ofp_header *oh, size_t length,
> const struct ofputil_msg_type **typep)
> {
> @@ -496,11 +496,11 @@ ofputil_decode_nxst_reply(const struct ofp_header *oh, size_t length,
> 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)
> + OFPERR_OFPBRC_BAD_SUBTYPE
> };
>
> const struct nicira_stats_msg *nsm;
> - int error;
> + enum ofperr error;
>
> error = check_nxstats_msg(oh, length);
> if (error) {
> @@ -512,20 +512,20 @@ ofputil_decode_nxst_reply(const struct ofp_header *oh, size_t length,
> ntohl(nsm->subtype), typep);
> }
>
> -static int
> +static enum ofperr
> check_stats_msg(const struct ofp_header *oh, size_t length)
> {
> if (length < sizeof(struct ofp_stats_msg)) {
> if (length == ntohs(oh->length)) {
> VLOG_WARN_RL(&bad_ofmsg_rl, "truncated stats message");
> }
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
>
> return 0;
> }
>
> -static int
> +static enum ofperr
> ofputil_decode_ofpst_request(const struct ofp_header *oh, size_t length,
> const struct ofputil_msg_type **typep)
> {
> @@ -562,11 +562,11 @@ ofputil_decode_ofpst_request(const struct ofp_header *oh, size_t length,
> 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)
> + OFPERR_OFPBRC_BAD_STAT
> };
>
> const struct ofp_stats_msg *request = (const struct ofp_stats_msg *) oh;
> - int error;
> + enum ofperr error;
>
> error = check_stats_msg(oh, length);
> if (error) {
> @@ -582,7 +582,7 @@ ofputil_decode_ofpst_request(const struct ofp_header *oh, size_t length,
> return error;
> }
>
> -static int
> +static enum ofperr
> ofputil_decode_ofpst_reply(const struct ofp_header *oh, size_t length,
> const struct ofputil_msg_type **typep)
> {
> @@ -619,11 +619,11 @@ ofputil_decode_ofpst_reply(const struct ofp_header *oh, size_t length,
> 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)
> + OFPERR_OFPBRC_BAD_STAT
> };
>
> const struct ofp_stats_msg *reply = (const struct ofp_stats_msg *) oh;
> - int error;
> + enum ofperr error;
>
> error = check_stats_msg(oh, length);
> if (error) {
> @@ -638,7 +638,7 @@ ofputil_decode_ofpst_reply(const struct ofp_header *oh, size_t length,
> return error;
> }
>
> -static int
> +static enum ofperr
> ofputil_decode_msg_type__(const struct ofp_header *oh, size_t length,
> const struct ofputil_msg_type **typep)
> {
> @@ -647,7 +647,7 @@ ofputil_decode_msg_type__(const struct ofp_header *oh, size_t length,
> OFPT_HELLO, "OFPT_HELLO",
> sizeof(struct ofp_hello), 1 },
>
> - { OFPUTIL_OFPT_ERROR, OFP10_VERSION,
> + { OFPUTIL_OFPT_ERROR, 0,
> OFPT_ERROR, "OFPT_ERROR",
> sizeof(struct ofp_error_msg), 1 },
>
> @@ -727,10 +727,10 @@ ofputil_decode_msg_type__(const struct ofp_header *oh, size_t length,
> static const struct ofputil_msg_category ofpt_category = {
> "OpenFlow message",
> ofpt_messages, ARRAY_SIZE(ofpt_messages),
> - OFP_MKERR(OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE)
> + OFPERR_OFPBRC_BAD_TYPE
> };
>
> - int error;
> + enum ofperr error;
>
> error = ofputil_lookup_openflow_message(&ofpt_category, oh->version,
> oh->type, typep);
> @@ -754,22 +754,21 @@ ofputil_decode_msg_type__(const struct ofp_header *oh, size_t length,
> return error;
> }
>
> -/* 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
> - * ofputil_msg_type_*() functions.
> +/* Decodes the message type represented by 'oh'. Returns 0 if successful or an
> + * OpenFlow error code on failure. Either way, stores in '*typep' a type
> + * structure that can be inspected with the ofputil_msg_type_*() functions.
> *
> * oh->length must indicate the correct length of the message (and must be at
> * least sizeof(struct ofp_header)).
> *
> * Success indicates that 'oh' is at least as long as the minimum-length
> * message of its type. */
> -int
> +enum ofperr
> ofputil_decode_msg_type(const struct ofp_header *oh,
> const struct ofputil_msg_type **typep)
> {
> size_t length = ntohs(oh->length);
> - int error;
> + enum ofperr error;
>
> error = ofputil_decode_msg_type__(oh, length, typep);
> if (!error) {
> @@ -783,18 +782,17 @@ ofputil_decode_msg_type(const struct ofp_header *oh,
>
> /* Decodes the message type represented by 'oh', of which only the first
> * 'length' bytes are available. 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
> - * ofputil_msg_type_*() functions. */
> -int
> + * code on failure. Either way, stores in '*typep' a type structure that can
> + * be inspected with the ofputil_msg_type_*() functions. */
> +enum ofperr
> ofputil_decode_msg_type_partial(const struct ofp_header *oh, size_t length,
> const struct ofputil_msg_type **typep)
> {
> - int error;
> + enum ofperr error;
>
> error = (length >= sizeof *oh
> ? ofputil_decode_msg_type__(oh, length, typep)
> - : ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN));
> + : OFPERR_OFPBRC_BAD_LEN);
> if (error) {
> *typep = &ofputil_invalid_type;
> }
> @@ -952,7 +950,7 @@ ofputil_make_flow_mod_table_id(bool flow_mod_table_id)
> * enabled, false otherwise.
> *
> * Does not validate the flow_mod actions. */
> -int
> +enum ofperr
> ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
> const struct ofp_header *oh, bool flow_mod_table_id)
> {
> @@ -967,7 +965,7 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
> /* Standard OpenFlow flow_mod. */
> const struct ofp_flow_mod *ofm;
> uint16_t priority;
> - int error;
> + enum ofperr error;
>
> /* Dissect the message. */
> ofm = ofpbuf_pull(&b, sizeof *ofm);
> @@ -1000,7 +998,7 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
> } else if (ofputil_msg_type_code(type) == OFPUTIL_NXT_FLOW_MOD) {
> /* Nicira extended flow_mod. */
> const struct nx_flow_mod *nfm;
> - int error;
> + enum ofperr error;
>
> /* Dissect the message. */
> nfm = ofpbuf_pull(&b, sizeof *nfm);
> @@ -1096,7 +1094,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
> return msg;
> }
>
> -static int
> +static enum ofperr
> ofputil_decode_ofpst_flow_request(struct ofputil_flow_stats_request *fsr,
> const struct ofp_header *oh,
> bool aggregate)
> @@ -1112,14 +1110,14 @@ ofputil_decode_ofpst_flow_request(struct ofputil_flow_stats_request *fsr,
> return 0;
> }
>
> -static int
> +static enum ofperr
> ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr,
> const struct ofp_header *oh,
> bool aggregate)
> {
> const struct nx_flow_stats_request *nfsr;
> struct ofpbuf b;
> - int error;
> + enum ofperr error;
>
> ofpbuf_use_const(&b, oh, ntohs(oh->length));
>
> @@ -1129,7 +1127,7 @@ ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr,
> return error;
> }
> if (b.size) {
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
>
> fsr->aggregate = aggregate;
> @@ -1142,7 +1140,7 @@ ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr,
> /* Converts an OFPST_FLOW, OFPST_AGGREGATE, NXST_FLOW, or NXST_AGGREGATE
> * request 'oh', into an abstract flow_stats_request in 'fsr'. Returns 0 if
> * successful, otherwise an OpenFlow error code. */
> -int
> +enum ofperr
> ofputil_decode_flow_stats_request(struct ofputil_flow_stats_request *fsr,
> const struct ofp_header *oh)
> {
> @@ -1426,7 +1424,7 @@ ofputil_encode_aggregate_stats_reply(
> /* Converts an OFPT_FLOW_REMOVED or NXT_FLOW_REMOVED message 'oh' into an
> * abstract ofputil_flow_removed in 'fr'. Returns 0 if successful, otherwise
> * an OpenFlow error code. */
> -int
> +enum ofperr
> ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
> const struct ofp_header *oh)
> {
> @@ -1462,7 +1460,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
> return error;
> }
> if (b.size) {
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
>
> fr->cookie = nfr->cookie;
> @@ -2059,8 +2057,8 @@ ofputil_frag_handling_from_string(const char *s, enum ofp_config_flags *flags)
>
> /* Checks that 'port' is a valid output port for the OFPAT_OUTPUT action, given
> * that the switch will never have more than 'max_ports' ports. Returns 0 if
> - * 'port' is valid, otherwise an ofp_mkerr() return code. */
> -int
> + * 'port' is valid, otherwise an OpenFlow return code. */
> +enum ofperr
> ofputil_check_output_port(uint16_t port, int max_ports)
> {
> switch (port) {
> @@ -2077,7 +2075,7 @@ ofputil_check_output_port(uint16_t port, int max_ports)
> if (port < max_ports) {
> return 0;
> }
> - return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT);
> + return OFPERR_OFPBAC_BAD_OUT_PORT;
> }
> }
>
> @@ -2143,16 +2141,16 @@ ofputil_format_port(uint16_t port, struct ds *s)
> ds_put_cstr(s, name);
> }
>
> -static int
> +static enum ofperr
> check_resubmit_table(const struct nx_action_resubmit *nar)
> {
> if (nar->pad[0] || nar->pad[1] || nar->pad[2]) {
> - return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + return OFPERR_OFPBAC_BAD_ARGUMENT;
> }
> return 0;
> }
>
> -static int
> +static enum ofperr
> check_output_reg(const struct nx_action_output_reg *naor,
> const struct flow *flow)
> {
> @@ -2160,7 +2158,7 @@ check_output_reg(const struct nx_action_output_reg *naor,
>
> for (i = 0; i < sizeof naor->zero; i++) {
> if (naor->zero[i]) {
> - return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + return OFPERR_OFPBAC_BAD_ARGUMENT;
> }
> }
>
> @@ -2168,7 +2166,7 @@ check_output_reg(const struct nx_action_output_reg *naor,
> nxm_decode_n_bits(naor->ofs_nbits), flow);
> }
>
> -int
> +enum ofperr
> validate_actions(const union ofp_action *actions, size_t n_actions,
> const struct flow *flow, int max_ports)
> {
> @@ -2176,20 +2174,16 @@ validate_actions(const union ofp_action *actions, size_t n_actions,
> size_t left;
>
> OFPUTIL_ACTION_FOR_EACH (a, left, actions, n_actions) {
> + enum ofperr error;
> uint16_t port;
> - int error;
> int code;
>
> code = ofputil_decode_action(a);
> if (code < 0) {
> - char *msg;
> -
> error = -code;
> - msg = ofputil_error_to_string(error);
> VLOG_WARN_RL(&bad_ofmsg_rl,
> "action decoding error at offset %td (%s)",
> - (a - actions) * sizeof *a, msg);
> - free(msg);
> + (a - actions) * sizeof *a, ofperr_get_name(error));
>
> return error;
> }
> @@ -2203,13 +2197,13 @@ validate_actions(const union ofp_action *actions, size_t n_actions,
>
> case OFPUTIL_OFPAT_SET_VLAN_VID:
> if (a->vlan_vid.vlan_vid & ~htons(0xfff)) {
> - error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + error = OFPERR_OFPBAC_BAD_ARGUMENT;
> }
> break;
>
> case OFPUTIL_OFPAT_SET_VLAN_PCP:
> if (a->vlan_pcp.vlan_pcp & ~7) {
> - error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
> + error = OFPERR_OFPBAC_BAD_ARGUMENT;
> }
> break;
>
> @@ -2217,7 +2211,7 @@ validate_actions(const union ofp_action *actions, size_t n_actions,
> port = ntohs(((const struct ofp_action_enqueue *) a)->port);
> if (port >= max_ports && port != OFPP_IN_PORT
> && port != OFPP_LOCAL) {
> - error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT);
> + error = OFPERR_OFPBAC_BAD_OUT_PORT;
> }
> break;
>
> @@ -2280,17 +2274,15 @@ validate_actions(const union ofp_action *actions, size_t n_actions,
> }
>
> if (error) {
> - char *msg = ofputil_error_to_string(error);
> VLOG_WARN_RL(&bad_ofmsg_rl, "bad action at offset %td (%s)",
> - (a - actions) * sizeof *a, msg);
> - free(msg);
> + (a - actions) * sizeof *a, ofperr_get_name(error));
> return error;
> }
> }
> if (left) {
> VLOG_WARN_RL(&bad_ofmsg_rl, "bad action format at offset %zu",
> (n_actions - left) * sizeof *a);
> - return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
> + return OFPERR_OFPBAC_BAD_LEN;
> }
> return 0;
> }
> @@ -2302,11 +2294,11 @@ struct ofputil_action {
> };
>
> static const struct ofputil_action action_bad_type
> - = { -OFP_MKERR(OFPET_BAD_ACTION, OFPBAC_BAD_TYPE), 0, UINT_MAX };
> + = { -OFPERR_OFPBAC_BAD_TYPE, 0, UINT_MAX };
> static const struct ofputil_action action_bad_len
> - = { -OFP_MKERR(OFPET_BAD_ACTION, OFPBAC_BAD_LEN), 0, UINT_MAX };
> + = { -OFPERR_OFPBAC_BAD_LEN, 0, UINT_MAX };
> static const struct ofputil_action action_bad_vendor
> - = { -OFP_MKERR(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR), 0, UINT_MAX };
> + = { -OFPERR_OFPBAC_BAD_VENDOR, 0, UINT_MAX };
>
> static const struct ofputil_action *
> ofputil_decode_ofpat_action(const union ofp_action *a)
> @@ -2357,8 +2349,8 @@ ofputil_decode_nxast_action(const union ofp_action *a)
> }
>
> /* Parses 'a' to determine its type. Returns a nonnegative OFPUTIL_OFPAT_* or
> - * OFPUTIL_NXAST_* constant if successful, otherwise a negative OpenFlow error
> - * code (as returned by ofp_mkerr()).
> + * OFPUTIL_NXAST_* constant if successful, otherwise a negative OFPERR_* error
> + * code.
> *
> * The caller must have already verified that 'a''s length is correct (that is,
> * a->header.len is nonzero and a multiple of sizeof(union ofp_action) and no
> @@ -2378,7 +2370,7 @@ ofputil_decode_action(const union ofp_action *a)
> switch (ntohl(a->vendor.vendor)) {
> case NX_VENDOR_ID:
> if (len < sizeof(struct nx_action_header)) {
> - return -ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
> + return -OFPERR_OFPBAC_BAD_LEN;
> }
> action = ofputil_decode_nxast_action(a);
> break;
> @@ -2390,7 +2382,7 @@ ofputil_decode_action(const union ofp_action *a)
>
> return (len >= action->min_len && len <= action->max_len
> ? action->code
> - : -ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN));
> + : -OFPERR_OFPBAC_BAD_LEN);
> }
>
> /* Parses 'a' and returns its type as an OFPUTIL_OFPAT_* or OFPUTIL_NXAST_*
> @@ -2617,207 +2609,6 @@ ofputil_normalize_rule(struct cls_rule *rule, enum nx_flow_format flow_format)
> }
> }
>
> -static uint32_t
> -vendor_code_to_id(uint8_t code)
> -{
> - switch (code) {
> -#define OFPUTIL_VENDOR(NAME, VENDOR_ID) case NAME: return VENDOR_ID;
> - OFPUTIL_VENDORS
> -#undef OFPUTIL_VENDOR
> - default:
> - return UINT32_MAX;
> - }
> -}
> -
> -static int
> -vendor_id_to_code(uint32_t id)
> -{
> - switch (id) {
> -#define OFPUTIL_VENDOR(NAME, VENDOR_ID) case VENDOR_ID: return NAME;
> - OFPUTIL_VENDORS
> -#undef OFPUTIL_VENDOR
> - default:
> - return -1;
> - }
> -}
> -
> -/* Creates and returns an OpenFlow message of type OFPT_ERROR with the error
> - * information taken from 'error', whose encoding must be as described in the
> - * large comment in ofp-util.h. If 'oh' is nonnull, then the error will use
> - * oh->xid as its transaction ID, and it will include up to the first 64 bytes
> - * of 'oh'.
> - *
> - * Returns NULL if 'error' is not an OpenFlow error code. */
> -struct ofpbuf *
> -ofputil_encode_error_msg(int error, const struct ofp_header *oh)
> -{
> - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> -
> - struct ofpbuf *buf;
> - const void *data;
> - size_t len;
> - uint8_t vendor;
> - uint16_t type;
> - uint16_t code;
> - ovs_be32 xid;
> -
> - if (!is_ofp_error(error)) {
> - /* We format 'error' with strerror() here since it seems likely to be
> - * a system errno value. */
> - VLOG_WARN_RL(&rl, "invalid OpenFlow error code %d (%s)",
> - error, strerror(error));
> - return NULL;
> - }
> -
> - if (oh) {
> - xid = oh->xid;
> - data = oh;
> - len = ntohs(oh->length);
> - if (len > 64) {
> - len = 64;
> - }
> - } else {
> - xid = 0;
> - data = NULL;
> - len = 0;
> - }
> -
> - vendor = get_ofp_err_vendor(error);
> - type = get_ofp_err_type(error);
> - code = get_ofp_err_code(error);
> - if (vendor == OFPUTIL_VENDOR_OPENFLOW) {
> - struct ofp_error_msg *oem;
> -
> - oem = make_openflow_xid(len + sizeof *oem, OFPT_ERROR, xid, &buf);
> - oem->type = htons(type);
> - oem->code = htons(code);
> - } else {
> - struct ofp_error_msg *oem;
> - struct nx_vendor_error *nve;
> - uint32_t vendor_id;
> -
> - vendor_id = vendor_code_to_id(vendor);
> - if (vendor_id == UINT32_MAX) {
> - VLOG_WARN_RL(&rl, "error %x contains invalid vendor code %d",
> - error, vendor);
> - return NULL;
> - }
> -
> - oem = make_openflow_xid(len + sizeof *oem + sizeof *nve,
> - OFPT_ERROR, xid, &buf);
> - oem->type = htons(NXET_VENDOR);
> - oem->code = htons(NXVC_VENDOR_ERROR);
> -
> - nve = (struct nx_vendor_error *)oem->data;
> - nve->vendor = htonl(vendor_id);
> - nve->type = htons(type);
> - nve->code = htons(code);
> - }
> -
> - if (len) {
> - buf->size -= len;
> - ofpbuf_put(buf, data, len);
> - }
> -
> - return buf;
> -}
> -
> -/* Decodes 'oh', which should be an OpenFlow OFPT_ERROR message, and returns an
> - * Open vSwitch internal error code in the format described in the large
> - * comment in ofp-util.h.
> - *
> - * If 'payload_ofs' is nonnull, on success '*payload_ofs' is set to the offset
> - * to the payload starting from 'oh' and on failure it is set to 0. */
> -int
> -ofputil_decode_error_msg(const struct ofp_header *oh, size_t *payload_ofs)
> -{
> - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> -
> - const struct ofp_error_msg *oem;
> - uint16_t type, code;
> - struct ofpbuf b;
> - int vendor;
> -
> - if (payload_ofs) {
> - *payload_ofs = 0;
> - }
> - if (oh->type != OFPT_ERROR) {
> - return EPROTO;
> - }
> -
> - ofpbuf_use_const(&b, oh, ntohs(oh->length));
> - oem = ofpbuf_try_pull(&b, sizeof *oem);
> - if (!oem) {
> - return EPROTO;
> - }
> -
> - type = ntohs(oem->type);
> - code = ntohs(oem->code);
> - if (type == NXET_VENDOR && code == NXVC_VENDOR_ERROR) {
> - const struct nx_vendor_error *nve = ofpbuf_try_pull(&b, sizeof *nve);
> - if (!nve) {
> - return EPROTO;
> - }
> -
> - vendor = vendor_id_to_code(ntohl(nve->vendor));
> - if (vendor < 0) {
> - VLOG_WARN_RL(&rl, "error contains unknown vendor ID %#"PRIx32,
> - ntohl(nve->vendor));
> - return EPROTO;
> - }
> - type = ntohs(nve->type);
> - code = ntohs(nve->code);
> - } else {
> - vendor = OFPUTIL_VENDOR_OPENFLOW;
> - }
> -
> - if (type >= 1024) {
> - VLOG_WARN_RL(&rl, "error contains type %"PRIu16" greater than "
> - "supported maximum value 1023", type);
> - return EPROTO;
> - }
> -
> - if (payload_ofs) {
> - *payload_ofs = (uint8_t *) b.data - (uint8_t *) oh;
> - }
> - return ofp_mkerr_vendor(vendor, type, code);
> -}
> -
> -void
> -ofputil_format_error(struct ds *s, int error)
> -{
> - if (is_errno(error)) {
> - ds_put_cstr(s, strerror(error));
> - } else {
> - uint16_t type = get_ofp_err_type(error);
> - uint16_t code = get_ofp_err_code(error);
> - const char *type_s = ofp_error_type_to_string(type);
> - const char *code_s = ofp_error_code_to_string(type, code);
> -
> - ds_put_format(s, "type ");
> - if (type_s) {
> - ds_put_cstr(s, type_s);
> - } else {
> - ds_put_format(s, "%"PRIu16, type);
> - }
> -
> - ds_put_cstr(s, ", code ");
> - if (code_s) {
> - ds_put_cstr(s, code_s);
> - } else {
> - ds_put_format(s, "%"PRIu16, code);
> - }
> - }
> -}
> -
> -char *
> -ofputil_error_to_string(int error)
> -{
> - struct ds s = DS_EMPTY_INITIALIZER;
> - ofputil_format_error(&s, error);
> - return ds_steal_cstr(&s);
> -}
> -
> /* Attempts to pull 'actions_len' bytes from the front of 'b'. Returns 0 if
> * successful, otherwise an OpenFlow error.
> *
> @@ -2829,7 +2620,7 @@ ofputil_error_to_string(int error)
> * do so, with validate_actions()). The caller is also responsible for making
> * sure that 'b->data' is initially aligned appropriately for "union
> * ofp_action". */
> -int
> +enum ofperr
> ofputil_pull_actions(struct ofpbuf *b, unsigned int actions_len,
> union ofp_action **actionsp, size_t *n_actionsp)
> {
> @@ -2853,7 +2644,7 @@ ofputil_pull_actions(struct ofpbuf *b, unsigned int actions_len,
> error:
> *actionsp = NULL;
> *n_actionsp = 0;
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
> + return OFPERR_OFPBRC_BAD_LEN;
> }
>
> bool
> diff --git a/lib/ofp-util.h b/lib/ofp-util.h
> index 909467f..88e998e 100644
> --- a/lib/ofp-util.h
> +++ b/lib/ofp-util.h
> @@ -88,15 +88,16 @@ enum ofputil_msg_code {
> };
>
> struct ofputil_msg_type;
> -int ofputil_decode_msg_type(const struct ofp_header *,
> - const struct ofputil_msg_type **);
> -int ofputil_decode_msg_type_partial(const struct ofp_header *, size_t length,
> +enum ofperr ofputil_decode_msg_type(const struct ofp_header *,
> const struct ofputil_msg_type **);
> +enum ofperr ofputil_decode_msg_type_partial(const struct ofp_header *,
> + size_t length,
> + const struct ofputil_msg_type **);
> enum ofputil_msg_code ofputil_msg_type_code(const struct ofputil_msg_type *);
> const char *ofputil_msg_type_name(const struct ofputil_msg_type *);
>
> /* Port numbers. */
> -int ofputil_check_output_port(uint16_t ofp_port, int max_ports);
> +enum ofperr ofputil_check_output_port(uint16_t ofp_port, int max_ports);
> bool ofputil_port_from_string(const char *, uint16_t *port);
> void ofputil_format_port(uint16_t port, struct ds *);
>
> @@ -142,8 +143,9 @@ struct ofputil_flow_mod {
> size_t n_actions;
> };
>
> -int ofputil_decode_flow_mod(struct ofputil_flow_mod *,
> - const struct ofp_header *, bool flow_mod_table_id);
> +enum ofperr ofputil_decode_flow_mod(struct ofputil_flow_mod *,
> + const struct ofp_header *,
> + bool flow_mod_table_id);
> struct ofpbuf *ofputil_encode_flow_mod(const struct ofputil_flow_mod *,
> enum nx_flow_format,
> bool flow_mod_table_id);
> @@ -156,8 +158,8 @@ struct ofputil_flow_stats_request {
> uint8_t table_id;
> };
>
> -int ofputil_decode_flow_stats_request(struct ofputil_flow_stats_request *,
> - const struct ofp_header *);
> +enum ofperr ofputil_decode_flow_stats_request(
> + struct ofputil_flow_stats_request *, const struct ofp_header *);
> struct ofpbuf *ofputil_encode_flow_stats_request(
> const struct ofputil_flow_stats_request *, enum nx_flow_format);
>
> @@ -204,8 +206,8 @@ struct ofputil_flow_removed {
> uint64_t byte_count; /* Byte count, UINT64_MAX if unknown. */
> };
>
> -int ofputil_decode_flow_removed(struct ofputil_flow_removed *,
> - const struct ofp_header *);
> +enum ofperr ofputil_decode_flow_removed(struct ofputil_flow_removed *,
> + const struct ofp_header *);
> struct ofpbuf *ofputil_encode_flow_removed(const struct ofputil_flow_removed *,
> enum nx_flow_format);
>
> @@ -397,160 +399,16 @@ ofputil_action_is_valid(const union ofp_action *a, size_t n_actions)
> ((LEFT) -= ntohs((ITER)->header.len) / sizeof(union ofp_action), \
> (ITER) = ofputil_action_next(ITER)))
>
> -int validate_actions(const union ofp_action *, size_t n_actions,
> - const struct flow *, int max_ports);
> +enum ofperr validate_actions(const union ofp_action *, size_t n_actions,
> + const struct flow *, int max_ports);
> bool action_outputs_to_port(const union ofp_action *, ovs_be16 port);
>
> -int ofputil_pull_actions(struct ofpbuf *, unsigned int actions_len,
> - union ofp_action **, size_t *);
> +enum ofperr ofputil_pull_actions(struct ofpbuf *, unsigned int actions_len,
> + union ofp_action **, size_t *);
>
> bool ofputil_actions_equal(const union ofp_action *a, size_t n_a,
> const union ofp_action *b, size_t n_b);
> union ofp_action *ofputil_actions_clone(const union ofp_action *, size_t n);
> -
> -/* OpenFlow vendors.
> - *
> - * These functions map OpenFlow 32-bit vendor IDs (as used in struct
> - * ofp_vendor_header) into 4-bit values to embed in an "int". The 4-bit values
> - * are only used internally in Open vSwitch and never appear on the wire, so
> - * particular codes used are not important.
> - */
> -
> -/* Vendor error numbers currently used in Open vSwitch. */
> -#define OFPUTIL_VENDORS \
> - /* vendor name vendor value */ \
> - OFPUTIL_VENDOR(OFPUTIL_VENDOR_OPENFLOW, 0x00000000) \
> - OFPUTIL_VENDOR(OFPUTIL_VENDOR_NICIRA, NX_VENDOR_ID)
> -
> -/* OFPUTIL_VENDOR_* definitions. */
> -enum ofputil_vendor_codes {
> -#define OFPUTIL_VENDOR(NAME, VENDOR_ID) NAME,
> - OFPUTIL_VENDORS
> - OFPUTIL_N_VENDORS
> -#undef OFPUTIL_VENDOR
> -};
> -
> -/* Error codes.
> - *
> - * We embed system errno values and OpenFlow standard and vendor extension
> - * error codes into a single 31-bit space using the following encoding.
> - * (Bit 31 is unused and assumed 0 to avoid negative "int" values.)
> - *
> - * 30 0
> - * +------------------------------------------------------+
> - * | 0 | success
> - * +------------------------------------------------------+
> - *
> - * 30 29 0
> - * +--+---------------------------------------------------+
> - * | 0| errno value | errno value
> - * +--+---------------------------------------------------+
> - *
> - * 30 29 26 25 16 15 0
> - * +--+-------+----------------+--------------------------+
> - * | 1| 0 | type | code | standard OpenFlow
> - * +--+-------+----------------+--------------------------+ error
> - *
> - * 30 29 26 25 16 15 0
> - * +--+-------+----------------+--------------------------+ Nicira
> - * | 1| vendor| type | code | NXET_VENDOR
> - * +--+-------+----------------+--------------------------+ error extension
> - *
> - * C and POSIX say that errno values are positive. We assume that they are
> - * less than 2**29. They are actually less than 65536 on at least Linux,
> - * FreeBSD, OpenBSD, and Windows.
> - *
> - * The 'vendor' field holds one of the OFPUTIL_VENDOR_* codes defined above.
> - * It must be nonzero.
> - *
> - * Negative values are not defined.
> - */
> -
> -/* Currently 4 bits are allocated to the "vendor" field. Make sure that all
> - * the vendor codes can fit. */
> -BUILD_ASSERT_DECL(OFPUTIL_N_VENDORS <= 16);
> -
> -/* These are macro versions of the functions defined below. The macro versions
> - * are intended for use in contexts where function calls are not allowed,
> - * e.g. static initializers and case labels. */
> -#define OFP_MKERR(TYPE, CODE) ((1 << 30) | ((TYPE) << 16) | (CODE))
> -#define OFP_MKERR_VENDOR(VENDOR, TYPE, CODE) \
> - ((1 << 30) | ((VENDOR) << 26) | ((TYPE) << 16) | (CODE))
> -#define OFP_MKERR_NICIRA(TYPE, CODE) \
> - OFP_MKERR_VENDOR(OFPUTIL_VENDOR_NICIRA, TYPE, CODE)
> -
> -/* Returns the standard OpenFlow error with the specified 'type' and 'code' as
> - * an integer. */
> -static inline int
> -ofp_mkerr(uint16_t type, uint16_t code)
> -{
> - return OFP_MKERR(type, code);
> -}
> -
> -/* Returns the OpenFlow vendor error with the specified 'vendor', 'type', and
> - * 'code' as an integer. 'vendor' must be an OFPUTIL_VENDOR_* constant. */
> -static inline int
> -ofp_mkerr_vendor(uint8_t vendor, uint16_t type, uint16_t code)
> -{
> - assert(vendor < OFPUTIL_N_VENDORS);
> - return OFP_MKERR_VENDOR(vendor, type, code);
> -}
> -
> -/* Returns the OpenFlow vendor error with Nicira as vendor, with the specific
> - * 'type' and 'code', as an integer. */
> -static inline int
> -ofp_mkerr_nicira(uint16_t type, uint16_t code)
> -{
> - return OFP_MKERR_NICIRA(type, code);
> -}
> -
> -/* Returns true if 'error' encodes an OpenFlow standard or vendor extension
> - * error codes as documented above. */
> -static inline bool
> -is_ofp_error(int error)
> -{
> - return (error & (1 << 30)) != 0;
> -}
> -
> -/* Returns true if 'error' appears to be a system errno value. */
> -static inline bool
> -is_errno(int error)
> -{
> - return !is_ofp_error(error);
> -}
> -
> -/* Returns the "vendor" part of the OpenFlow error code 'error' (which must be
> - * in the format explained above). This is normally one of the
> - * OFPUTIL_VENDOR_* constants. Returns OFPUTIL_VENDOR_OPENFLOW (0) for a
> - * standard OpenFlow error. */
> -static inline uint8_t
> -get_ofp_err_vendor(int error)
> -{
> - return (error >> 26) & 0xf;
> -}
> -
> -/* Returns the "type" part of the OpenFlow error code 'error' (which must be in
> - * the format explained above). */
> -static inline uint16_t
> -get_ofp_err_type(int error)
> -{
> - return (error >> 16) & 0x3ff;
> -}
> -
> -/* Returns the "code" part of the OpenFlow error code 'error' (which must be in
> - * the format explained above). */
> -static inline uint16_t
> -get_ofp_err_code(int error)
> -{
> - return error & 0xffff;
> -}
> -
> -struct ofpbuf *ofputil_encode_error_msg(int error, const struct ofp_header *);
> -int ofputil_decode_error_msg(const struct ofp_header *, size_t *payload_ofs);
> -
> -/* String versions of errors. */
> -void ofputil_format_error(struct ds *, int error);
> -char *ofputil_error_to_string(int error);
>
> /* Handy utility for parsing flows and actions. */
> bool ofputil_parse_key_value(char **stringp, char **keyp, char **valuep);
> diff --git a/lib/vconn.c b/lib/vconn.c
> index 6ea9366..8e6374e 100644
> --- a/lib/vconn.c
> +++ b/lib/vconn.c
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2008, 2009, 2010 Nicira Networks.
> + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -27,6 +27,7 @@
> #include "dynamic-string.h"
> #include "fatal-signal.h"
> #include "flow.h"
> +#include "ofp-errors.h"
> #include "ofp-print.h"
> #include "ofp-util.h"
> #include "ofpbuf.h"
> @@ -442,7 +443,6 @@ vcs_recv_hello(struct vconn *vconn)
> static void
> vcs_send_error(struct vconn *vconn)
> {
> - struct ofp_error_msg *error;
> struct ofpbuf *b;
> char s[128];
> int retval;
> @@ -450,11 +450,8 @@ vcs_send_error(struct vconn *vconn)
> snprintf(s, sizeof s, "We support versions 0x%02x to 0x%02x inclusive but "
> "you support no later than version 0x%02"PRIx8".",
> vconn->min_version, OFP_VERSION, vconn->version);
> - error = make_openflow(sizeof *error, OFPT_ERROR, &b);
> - error->type = htons(OFPET_HELLO_FAILED);
> - error->code = htons(OFPHFC_INCOMPATIBLE);
> - ofpbuf_put(b, s, strlen(s));
> - update_openflow_length(b);
> + b = ofperr_encode_hello(OFPERR_OFPHFC_INCOMPATIBLE,
> + ofperr_domain_from_version(vconn->version), s);
> retval = do_send(vconn, b);
> if (retval) {
> ofpbuf_delete(b);
> diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
> index 6432ba6..63cb133 100644
> --- a/ofproto/connmgr.c
> +++ b/ofproto/connmgr.c
> @@ -821,24 +821,22 @@ ofconn_send_replies(const struct ofconn *ofconn, struct list *replies)
> }
> }
>
> -/* Sends 'error', which should be an OpenFlow error created with
> - * e.g. ofp_mkerr(), on 'ofconn', as a reply to 'request'. Only at most the
> +/* Sends 'error' on 'ofconn', as a reply to 'request'. Only at most the
> * first 64 bytes of 'request' are used. */
> void
> ofconn_send_error(const struct ofconn *ofconn,
> - const struct ofp_header *request, int error)
> + const struct ofp_header *request, enum ofperr error)
> {
> - struct ofpbuf *msg;
> + struct ofpbuf *reply;
>
> - msg = ofputil_encode_error_msg(error, request);
> - if (msg) {
> + reply = ofperr_encode_reply(error, request);
> + if (reply) {
> static struct vlog_rate_limit err_rl = VLOG_RATE_LIMIT_INIT(10, 10);
>
> if (!VLOG_DROP_INFO(&err_rl)) {
> const struct ofputil_msg_type *type;
> const char *type_name;
> size_t request_len;
> - char *error_s;
>
> request_len = ntohs(request->length);
> type_name = (!ofputil_decode_msg_type_partial(request,
> @@ -847,17 +845,16 @@ ofconn_send_error(const struct ofconn *ofconn,
> ? ofputil_msg_type_name(type)
> : "invalid");
>
> - error_s = ofputil_error_to_string(error);
> VLOG_INFO("%s: sending %s error reply to %s message",
> - rconn_get_name(ofconn->rconn), error_s, type_name);
> - free(error_s);
> + rconn_get_name(ofconn->rconn), ofperr_to_string(error),
> + type_name);
> }
> - ofconn_send_reply(ofconn, msg);
> + ofconn_send_reply(ofconn, reply);
> }
> }
>
> /* Same as pktbuf_retrieve(), using the pktbuf owned by 'ofconn'. */
> -int
> +enum ofperr
> ofconn_pktbuf_retrieve(struct ofconn *ofconn, uint32_t id,
> struct ofpbuf **bufferp, uint16_t *in_port)
> {
> diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h
> index 0224352..0040c98 100644
> --- a/ofproto/connmgr.h
> +++ b/ofproto/connmgr.h
> @@ -19,6 +19,7 @@
>
> #include "hmap.h"
> #include "list.h"
> +#include "ofp-errors.h"
> #include "ofproto.h"
> #include "openflow/nicira-ext.h"
> #include "openvswitch/types.h"
> @@ -94,10 +95,10 @@ void ofconn_set_miss_send_len(struct ofconn *, int miss_send_len);
> void ofconn_send_reply(const struct ofconn *, struct ofpbuf *);
> void ofconn_send_replies(const struct ofconn *, struct list *);
> void ofconn_send_error(const struct ofconn *, const struct ofp_header *request,
> - int error);
> + enum ofperr);
>
> -int ofconn_pktbuf_retrieve(struct ofconn *, uint32_t id,
> - struct ofpbuf **bufferp, uint16_t *in_port);
> +enum ofperr ofconn_pktbuf_retrieve(struct ofconn *, uint32_t id,
> + struct ofpbuf **bufferp, uint16_t *in_port);
>
> bool ofconn_has_pending_opgroups(const struct ofconn *);
> void ofconn_add_opgroup(struct ofconn *, struct list *);
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index e68bec3..2d3599c 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -3822,14 +3822,14 @@ rule_dealloc(struct rule *rule_)
> free(rule);
> }
>
> -static int
> +static enum ofperr
> rule_construct(struct rule *rule_)
> {
> struct rule_dpif *rule = rule_dpif_cast(rule_);
> struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
> struct rule_dpif *victim;
> uint8_t table_id;
> - int error;
> + enum ofperr error;
>
> error = validate_actions(rule->up.actions, rule->up.n_actions,
> &rule->up.cr.flow, ofproto->max_ports);
> @@ -3906,7 +3906,7 @@ rule_get_stats(struct rule *rule_, uint64_t *packets, uint64_t *bytes)
> }
> }
>
> -static int
> +static enum ofperr
> rule_execute(struct rule *rule_, const struct flow *flow,
> struct ofpbuf *packet)
> {
> @@ -3936,7 +3936,7 @@ rule_modify_actions(struct rule *rule_)
> {
> struct rule_dpif *rule = rule_dpif_cast(rule_);
> struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
> - int error;
> + enum ofperr error;
>
> error = validate_actions(rule->up.actions, rule->up.n_actions,
> &rule->up.cr.flow, ofproto->max_ports);
> @@ -4434,9 +4434,8 @@ xlate_learn_action(struct action_xlate_ctx *ctx,
>
> error = ofproto_flow_mod(&ctx->ofproto->up, &fm);
> if (error && !VLOG_DROP_WARN(&rl)) {
> - char *msg = ofputil_error_to_string(error);
> - VLOG_WARN("learning action failed to modify flow table (%s)", msg);
> - free(msg);
> + VLOG_WARN("learning action failed to modify flow table (%s)",
> + ofperr_get_name(error));
> }
>
> free(fm.actions);
> @@ -5411,16 +5410,16 @@ set_frag_handling(struct ofproto *ofproto_,
> }
> }
>
> -static int
> +static enum ofperr
> packet_out(struct ofproto *ofproto_, struct ofpbuf *packet,
> const struct flow *flow,
> const union ofp_action *ofp_actions, size_t n_ofp_actions)
> {
> struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
> - int error;
> + enum ofperr error;
>
> if (flow->in_port >= ofproto->max_ports && flow->in_port < OFPP_MAX) {
> - return ofp_mkerr_nicira(OFPET_BAD_REQUEST, NXBRC_BAD_IN_PORT);
> + return OFPERR_NXBRC_BAD_IN_PORT;
> }
>
> error = validate_actions(ofp_actions, n_ofp_actions, flow,
> diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
> index 6c8583e..b995831 100644
> --- a/ofproto/ofproto-provider.h
> +++ b/ofproto/ofproto-provider.h
> @@ -23,6 +23,7 @@
> #include "cfm.h"
> #include "classifier.h"
> #include "list.h"
> +#include "ofp-errors.h"
> #include "shash.h"
> #include "timeval.h"
>
> @@ -140,7 +141,7 @@ rule_from_cls_rule(const struct cls_rule *cls_rule)
> void ofproto_rule_expire(struct rule *, uint8_t reason);
> void ofproto_rule_destroy(struct rule *);
>
> -void ofoperation_complete(struct ofoperation *, int status);
> +void ofoperation_complete(struct ofoperation *, enum ofperr);
> struct rule *ofoperation_get_victim(struct ofoperation *);
>
> /* ofproto class structure, to be defined by each ofproto implementation.
> @@ -235,7 +236,7 @@ struct rule *ofoperation_get_victim(struct ofoperation *);
> *
> * Most of these functions return 0 if they are successful or a positive error
> * code on failure. Depending on the function, valid error codes are either
> - * errno values or OpenFlow error codes constructed with ofp_mkerr().
> + * errno values or OFPERR_* OpenFlow error codes.
> *
> * Most of these functions are expected to execute synchronously, that is, to
> * block as necessary to obtain a result. Thus, these functions may return
> @@ -624,7 +625,7 @@ struct ofproto_class {
>
> /* Chooses an appropriate table for 'cls_rule' within 'ofproto'. On
> * success, stores the table ID into '*table_idp' and returns 0. On
> - * failure, returns an OpenFlow error code (as returned by ofp_mkerr()).
> + * failure, returns an OpenFlow error code.
> *
> * The choice of table should be a function of 'cls_rule' and 'ofproto''s
> * datapath capabilities. It should not depend on the flows already in
> @@ -636,9 +637,9 @@ struct ofproto_class {
> * should choose one arbitrarily (but deterministically).
> *
> * If this function is NULL then table 0 is always chosen. */
> - int (*rule_choose_table)(const struct ofproto *ofproto,
> - const struct cls_rule *cls_rule,
> - uint8_t *table_idp);
> + enum ofperr (*rule_choose_table)(const struct ofproto *ofproto,
> + const struct cls_rule *cls_rule,
> + uint8_t *table_idp);
>
> /* Life-cycle functions for a "struct rule" (see "Life Cycle" above).
> *
> @@ -749,8 +750,8 @@ struct ofproto_class {
> *
> * * Call ofoperation_complete() and return 0.
> *
> - * * Return an OpenFlow error code (as returned by ofp_mkerr()). (Do
> - * not call ofoperation_complete() in this case.)
> + * * Return an OpenFlow error code. (Do not call
> + * ofoperation_complete() in this case.)
> *
> * Either way, ->rule_destruct() will not be called for 'rule', but
> * ->rule_dealloc() will be.
> @@ -775,7 +776,7 @@ struct ofproto_class {
> *
> * Rule destruction must not fail. */
> struct rule *(*rule_alloc)(void);
> - int (*rule_construct)(struct rule *rule);
> + enum ofperr (*rule_construct)(struct rule *rule);
> void (*rule_destruct)(struct rule *rule);
> void (*rule_dealloc)(struct rule *rule);
>
> @@ -799,10 +800,9 @@ struct ofproto_class {
> *
> * The statistics for 'packet' should be included in 'rule'.
> *
> - * Returns 0 if successful, otherwise an OpenFlow error code (as returned
> - * by ofp_mkerr()). */
> - int (*rule_execute)(struct rule *rule, const struct flow *flow,
> - struct ofpbuf *packet);
> + * Returns 0 if successful, otherwise an OpenFlow error code. */
> + enum ofperr (*rule_execute)(struct rule *rule, const struct flow *flow,
> + struct ofpbuf *packet);
>
> /* When ->rule_modify_actions() is called, the caller has already replaced
> * the OpenFlow actions in 'rule' by a new set. (The original actions are
> @@ -866,8 +866,7 @@ struct ofproto_class {
> *
> * This function must validate that the 'n_actions' elements in 'actions'
> * are well-formed OpenFlow actions that can be correctly implemented by
> - * the datapath. If not, then it should return an OpenFlow error code (as
> - * returned by ofp_mkerr()).
> + * the datapath. If not, then it should return an OpenFlow error code.
> *
> * 'flow' reflects the flow information for 'packet'. All of the
> * information in 'flow' is extracted from 'packet', except for
> @@ -877,12 +876,11 @@ struct ofproto_class {
> * 'packet' is not matched against the OpenFlow flow table, so its
> * statistics should not be included in OpenFlow flow statistics.
> *
> - * Returns 0 if successful, otherwise an OpenFlow error code (as returned
> - * by ofp_mkerr()). */
> - int (*packet_out)(struct ofproto *ofproto, struct ofpbuf *packet,
> - const struct flow *flow,
> - const union ofp_action *actions,
> - size_t n_actions);
> + * Returns 0 if successful, otherwise an OpenFlow error code. */
> + enum ofperr (*packet_out)(struct ofproto *ofproto, struct ofpbuf *packet,
> + const struct flow *flow,
> + const union ofp_action *actions,
> + size_t n_actions);
>
> /* ## ------------------------- ## */
> /* ## OFPP_NORMAL configuration ## */
> @@ -1095,10 +1093,11 @@ int ofproto_class_unregister(const struct ofproto_class *);
> *
> * ofproto.c also uses this value internally for additional (similar) purposes.
> *
> - * This particular value is a good choice because it is negative (so it won't
> - * collide with any errno value or any value returned by ofp_mkerr()) and large
> - * (so it won't accidentally collide with EOF or a negative errno value). */
> -enum { OFPROTO_POSTPONE = -100000 };
> + * This particular value is a good choice because it is large, so that it does
> + * not collide with any errno value, but not large enough to collide with an
> + * OFPERR_* value. */
> +enum { OFPROTO_POSTPONE = 1 << 16 };
> +BUILD_ASSERT_DECL(OFPROTO_POSTPONE < OFPERR_OFS);
>
> int ofproto_flow_mod(struct ofproto *, const struct ofputil_flow_mod *);
> void ofproto_add_flow(struct ofproto *, const struct cls_rule *,
> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> index b7433fc..ccb5f91 100644
> --- a/ofproto/ofproto.c
> +++ b/ofproto/ofproto.c
> @@ -31,6 +31,7 @@
> #include "hmap.h"
> #include "netdev.h"
> #include "nx-match.h"
> +#include "ofp-errors.h"
> #include "ofp-print.h"
> #include "ofp-util.h"
> #include "ofpbuf.h"
> @@ -136,13 +137,13 @@ static void ofproto_rule_send_removed(struct rule *, uint8_t reason);
>
> static void ofopgroup_destroy(struct ofopgroup *);
>
> -static int add_flow(struct ofproto *, struct ofconn *,
> - const struct ofputil_flow_mod *,
> - const struct ofp_header *);
> +static enum ofperr add_flow(struct ofproto *, struct ofconn *,
> + const struct ofputil_flow_mod *,
> + const struct ofp_header *);
>
> static bool handle_openflow(struct ofconn *, struct ofpbuf *);
> -static int handle_flow_mod__(struct ofproto *, struct ofconn *,
> - const struct ofputil_flow_mod *,
> +static enum ofperr handle_flow_mod__(struct ofproto *, struct ofconn *,
> + const struct ofputil_flow_mod *,
> const struct ofp_header *);
>
> static void update_port(struct ofproto *, const char *devname);
> @@ -1191,9 +1192,8 @@ ofproto_add_flow(struct ofproto *ofproto, const struct cls_rule *cls_rule,
> }
>
> /* Executes the flow modification specified in 'fm'. Returns 0 on success, an
> - * OpenFlow error code as encoded by ofp_mkerr() on failure, or
> - * OFPROTO_POSTPONE if the operation cannot be initiated now but may be retried
> - * later.
> + * OFPERR_* OpenFlow error code on failure, or OFPROTO_POSTPONE if the
> + * operation cannot be initiated now but may be retried later.
> *
> * This is a helper function for in-band control and fail-open. */
> int
> @@ -1702,14 +1702,14 @@ rule_is_hidden(const struct rule *rule)
> return rule->cr.priority > UINT16_MAX;
> }
>
> -static int
> +static enum ofperr
> handle_echo_request(struct ofconn *ofconn, const struct ofp_header *oh)
> {
> ofconn_send_reply(ofconn, make_echo_reply(oh));
> return 0;
> }
>
> -static int
> +static enum ofperr
> handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh)
> {
> struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
> @@ -1741,7 +1741,7 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh)
> return 0;
> }
>
> -static int
> +static enum ofperr
> handle_get_config_request(struct ofconn *ofconn, const struct ofp_header *oh)
> {
> struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
> @@ -1757,7 +1757,7 @@ handle_get_config_request(struct ofconn *ofconn, const struct ofp_header *oh)
> return 0;
> }
>
> -static int
> +static enum ofperr
> handle_set_config(struct ofconn *ofconn, const struct ofp_switch_config *osc)
> {
> struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
> @@ -1786,20 +1786,22 @@ handle_set_config(struct ofconn *ofconn, const struct ofp_switch_config *osc)
> }
>
> /* Checks whether 'ofconn' is a slave controller. If so, returns an OpenFlow
> - * error message code (composed with ofp_mkerr()) for the caller to propagate
> - * upward. Otherwise, returns 0. */
> -static int
> -reject_slave_controller(const struct ofconn *ofconn)
> + * error message code for the caller to propagate upward. Otherwise, returns
> + * 0.
> + *
> + * The log message mentions 'msg_type'. */
> +static enum ofperr
> +reject_slave_controller(struct ofconn *ofconn)
> {
> if (ofconn_get_type(ofconn) == OFCONN_PRIMARY
> && ofconn_get_role(ofconn) == NX_ROLE_SLAVE) {
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_EPERM);
> + return OFPERR_OFPBRC_EPERM;
> } else {
> return 0;
> }
> }
>
> -static int
> +static enum ofperr
> handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
> {
> struct ofproto *p = ofconn_get_ofproto(ofconn);
> @@ -1809,8 +1811,8 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
> struct ofpbuf request;
> struct flow flow;
> size_t n_ofp_actions;
> + enum ofperr error;
> uint16_t in_port;
> - int error;
>
> COVERAGE_INC(ofproto_packet_out);
>
> @@ -1850,7 +1852,7 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
> * above) are valid. */
> in_port = ntohs(opo->in_port);
> if (in_port >= OFPP_MAX && in_port != OFPP_LOCAL && in_port != OFPP_NONE) {
> - return ofp_mkerr_nicira(OFPET_BAD_REQUEST, NXBRC_BAD_IN_PORT);
> + return OFPERR_NXBRC_BAD_IN_PORT;
> }
>
> /* Send out packet. */
> @@ -1884,7 +1886,7 @@ update_port_config(struct ofport *port, ovs_be32 config, ovs_be32 mask)
> }
> }
>
> -static int
> +static enum ofperr
> handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh)
> {
> struct ofproto *p = ofconn_get_ofproto(ofconn);
> @@ -1899,9 +1901,9 @@ handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh)
>
> port = ofproto_get_port(p, ntohs(opm->port_no));
> if (!port) {
> - return ofp_mkerr(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_PORT);
> + return OFPERR_OFPPMFC_BAD_PORT;
> } else if (memcmp(port->opp.hw_addr, opm->hw_addr, OFP_ETH_ALEN)) {
> - return ofp_mkerr(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_HW_ADDR);
> + return OFPERR_OFPPMFC_BAD_HW_ADDR;
> } else {
> update_port_config(port, opm->config, opm->mask);
> if (opm->advertise) {
> @@ -1911,7 +1913,7 @@ handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh)
> return 0;
> }
>
> -static int
> +static enum ofperr
> handle_desc_stats_request(struct ofconn *ofconn,
> const struct ofp_stats_msg *request)
> {
> @@ -1930,7 +1932,7 @@ handle_desc_stats_request(struct ofconn *ofconn,
> return 0;
> }
>
> -static int
> +static enum ofperr
> handle_table_stats_request(struct ofconn *ofconn,
> const struct ofp_stats_msg *request)
> {
> @@ -1984,7 +1986,7 @@ append_port_stat(struct ofport *port, struct list *replies)
> put_32aligned_be64(&ops->collisions, htonll(stats.collisions));
> }
>
> -static int
> +static enum ofperr
> handle_port_stats_request(struct ofconn *ofconn,
> const struct ofp_port_stats_request *psr)
> {
> @@ -2018,12 +2020,12 @@ calc_flow_duration__(long long int start, uint32_t *sec, uint32_t *nsec)
>
> /* Checks whether 'table_id' is 0xff or a valid table ID in 'ofproto'. Returns
> * 0 if 'table_id' is OK, otherwise an OpenFlow error code. */
> -static int
> +static enum ofperr
> check_table_id(const struct ofproto *ofproto, uint8_t table_id)
> {
> return (table_id == 0xff || table_id < ofproto->n_tables
> ? 0
> - : ofp_mkerr_nicira(OFPET_BAD_REQUEST, NXBRC_BAD_TABLE_ID));
> + : OFPERR_NXBRC_BAD_TABLE_ID);
>
> }
>
> @@ -2079,13 +2081,13 @@ next_matching_table(struct ofproto *ofproto,
> * Hidden rules are always omitted.
> *
> * Returns 0 on success, otherwise an OpenFlow error code. */
> -static int
> +static enum ofperr
> collect_rules_loose(struct ofproto *ofproto, uint8_t table_id,
> const struct cls_rule *match, uint16_t out_port,
> struct list *rules)
> {
> struct classifier *cls;
> - int error;
> + enum ofperr error;
>
> error = check_table_id(ofproto, table_id);
> if (error) {
> @@ -2121,7 +2123,7 @@ collect_rules_loose(struct ofproto *ofproto, uint8_t table_id,
> * Hidden rules are always omitted.
> *
> * Returns 0 on success, otherwise an OpenFlow error code. */
> -static int
> +static enum ofperr
> collect_rules_strict(struct ofproto *ofproto, uint8_t table_id,
> const struct cls_rule *match, uint16_t out_port,
> struct list *rules)
> @@ -2151,7 +2153,7 @@ collect_rules_strict(struct ofproto *ofproto, uint8_t table_id,
> return 0;
> }
>
> -static int
> +static enum ofperr
> handle_flow_stats_request(struct ofconn *ofconn,
> const struct ofp_stats_msg *osm)
> {
> @@ -2160,7 +2162,7 @@ handle_flow_stats_request(struct ofconn *ofconn,
> struct list replies;
> struct list rules;
> struct rule *rule;
> - int error;
> + enum ofperr error;
>
> error = ofputil_decode_flow_stats_request(&fsr, &osm->header);
> if (error) {
> @@ -2279,7 +2281,7 @@ ofproto_port_get_cfm_remote_mpids(const struct ofproto *ofproto,
> : -1);
> }
>
> -static int
> +static enum ofperr
> handle_aggregate_stats_request(struct ofconn *ofconn,
> const struct ofp_stats_msg *osm)
> {
> @@ -2290,7 +2292,7 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
> struct ofpbuf *reply;
> struct list rules;
> struct rule *rule;
> - int error;
> + enum ofperr error;
>
> error = ofputil_decode_flow_stats_request(&request, &osm->header);
> if (error) {
> @@ -2386,7 +2388,7 @@ handle_queue_stats_for_port(struct ofport *port, uint32_t queue_id,
> }
> }
>
> -static int
> +static enum ofperr
> handle_queue_stats_request(struct ofconn *ofconn,
> const struct ofp_queue_stats_request *qsr)
> {
> @@ -2413,7 +2415,7 @@ handle_queue_stats_request(struct ofconn *ofconn,
> }
> } else {
> ofpbuf_list_delete(&cbdata.replies);
> - return ofp_mkerr(OFPET_QUEUE_OP_FAILED, OFPQOFC_BAD_PORT);
> + return OFPERR_OFPQOFC_BAD_PORT;
> }
> ofconn_send_replies(ofconn, &cbdata.replies);
>
> @@ -2445,12 +2447,12 @@ is_flow_deletion_pending(const struct ofproto *ofproto,
> *
> * Adds the flow specified by 'ofm', which is followed by 'n_actions'
> * ofp_actions, to the ofproto's flow table. Returns 0 on success, an OpenFlow
> - * error code as encoded by ofp_mkerr() on failure, or OFPROTO_POSTPONE if the
> - * operation cannot be initiated now but may be retried later.
> + * error code on failure, or OFPROTO_POSTPONE if the operation cannot be
> + * initiated now but may be retried later.
> *
> * 'ofconn' is used to retrieve the packet buffer specified in ofm->buffer_id,
> * if any. */
> -static int
> +static enum ofperr
> add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
> const struct ofputil_flow_mod *fm, const struct ofp_header *request)
> {
> @@ -2482,13 +2484,13 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
> } else if (fm->table_id < ofproto->n_tables) {
> table = &ofproto->tables[fm->table_id];
> } else {
> - return ofp_mkerr_nicira(OFPET_FLOW_MOD_FAILED, NXFMFC_BAD_TABLE_ID);
> + return OFPERR_NXFMFC_BAD_TABLE_ID;
> }
>
> /* Check for overlap, if requested. */
> if (fm->flags & OFPFF_CHECK_OVERLAP
> && classifier_rule_overlaps(table, &fm->cr)) {
> - return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP);
> + return OFPERR_OFPFMFC_OVERLAP;
> }
>
> /* Serialize against pending deletion. */
> @@ -2552,7 +2554,7 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
> * if any.
> *
> * Returns 0 on success, otherwise an OpenFlow error code. */
> -static int
> +static enum ofperr
> modify_flows__(struct ofproto *ofproto, struct ofconn *ofconn,
> const struct ofputil_flow_mod *fm,
> const struct ofp_header *request, struct list *rules)
> @@ -2580,12 +2582,12 @@ modify_flows__(struct ofproto *ofproto, struct ofconn *ofconn,
> return 0;
> }
>
> -/* Implements OFPFC_MODIFY. Returns 0 on success or an OpenFlow error code as
> - * encoded by ofp_mkerr() on failure.
> +/* Implements OFPFC_MODIFY. Returns 0 on success or an OpenFlow error code on
> + * failure.
> *
> * 'ofconn' is used to retrieve the packet buffer specified in fm->buffer_id,
> * if any. */
> -static int
> +static enum ofperr
> modify_flows_loose(struct ofproto *ofproto, struct ofconn *ofconn,
> const struct ofputil_flow_mod *fm,
> const struct ofp_header *request)
> @@ -2601,11 +2603,11 @@ modify_flows_loose(struct ofproto *ofproto, struct ofconn *ofconn,
> }
>
> /* Implements OFPFC_MODIFY_STRICT. Returns 0 on success or an OpenFlow error
> - * code as encoded by ofp_mkerr() on failure.
> + * code on failure.
> *
> * 'ofconn' is used to retrieve the packet buffer specified in fm->buffer_id,
> * if any. */
> -static int
> +static enum ofperr
> modify_flow_strict(struct ofproto *ofproto, struct ofconn *ofconn,
> const struct ofputil_flow_mod *fm,
> const struct ofp_header *request)
> @@ -2627,7 +2629,7 @@ modify_flow_strict(struct ofproto *ofproto, struct ofconn *ofconn,
> /* Deletes the rules listed in 'rules'.
> *
> * Returns 0 on success, otherwise an OpenFlow error code. */
> -static int
> +static enum ofperr
> delete_flows__(struct ofproto *ofproto, struct ofconn *ofconn,
> const struct ofp_header *request, struct list *rules)
> {
> @@ -2648,13 +2650,13 @@ delete_flows__(struct ofproto *ofproto, struct ofconn *ofconn,
> }
>
> /* Implements OFPFC_DELETE. */
> -static int
> +static enum ofperr
> delete_flows_loose(struct ofproto *ofproto, struct ofconn *ofconn,
> const struct ofputil_flow_mod *fm,
> const struct ofp_header *request)
> {
> struct list rules;
> - int error;
> + enum ofperr error;
>
> error = collect_rules_loose(ofproto, fm->table_id, &fm->cr, fm->out_port,
> &rules);
> @@ -2665,13 +2667,13 @@ delete_flows_loose(struct ofproto *ofproto, struct ofconn *ofconn,
> }
>
> /* Implements OFPFC_DELETE_STRICT. */
> -static int
> +static enum ofperr
> delete_flow_strict(struct ofproto *ofproto, struct ofconn *ofconn,
> const struct ofputil_flow_mod *fm,
> const struct ofp_header *request)
> {
> struct list rules;
> - int error;
> + enum ofperr error;
>
> error = collect_rules_strict(ofproto, fm->table_id, &fm->cr, fm->out_port,
> &rules);
> @@ -2724,11 +2726,11 @@ ofproto_rule_expire(struct rule *rule, uint8_t reason)
> ofopgroup_submit(group);
> }
>
> -static int
> +static enum ofperr
> handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
> {
> struct ofputil_flow_mod fm;
> - int error;
> + enum ofperr error;
>
> error = reject_slave_controller(ofconn);
> if (error) {
> @@ -2746,13 +2748,13 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
> if (fm.flags & OFPFF_EMERG) {
> /* There isn't a good fit for an error code, so just state that the
> * flow table is full. */
> - return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL);
> + return OFPERR_OFPFMFC_ALL_TABLES_FULL;
> }
>
> return handle_flow_mod__(ofconn_get_ofproto(ofconn), ofconn, &fm, oh);
> }
>
> -static int
> +static enum ofperr
> handle_flow_mod__(struct ofproto *ofproto, struct ofconn *ofconn,
> const struct ofputil_flow_mod *fm,
> const struct ofp_header *oh)
> @@ -2783,11 +2785,11 @@ handle_flow_mod__(struct ofproto *ofproto, struct ofconn *ofconn,
> VLOG_WARN_RL(&rl, "flow_mod has explicit table_id but "
> "flow_mod_table_id extension is not enabled");
> }
> - return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_COMMAND);
> + return OFPERR_OFPFMFC_BAD_COMMAND;
> }
> }
>
> -static int
> +static enum ofperr
> handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh)
> {
> struct nx_role_request *nrr = (struct nx_role_request *) oh;
> @@ -2796,13 +2798,13 @@ handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh)
> uint32_t role;
>
> if (ofconn_get_type(ofconn) != OFCONN_PRIMARY) {
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_EPERM);
> + return OFPERR_OFPBRC_EPERM;
> }
>
> role = ntohl(nrr->role);
> if (role != NX_ROLE_OTHER && role != NX_ROLE_MASTER
> && role != NX_ROLE_SLAVE) {
> - return ofp_mkerr_nicira(OFPET_BAD_REQUEST, NXBRC_BAD_ROLE);
> + return OFPERR_NXBRC_BAD_ROLE;
> }
>
> if (ofconn_get_role(ofconn) != role
> @@ -2819,7 +2821,7 @@ handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh)
> return 0;
> }
>
> -static int
> +static enum ofperr
> handle_nxt_flow_mod_table_id(struct ofconn *ofconn,
> const struct ofp_header *oh)
> {
> @@ -2830,7 +2832,7 @@ handle_nxt_flow_mod_table_id(struct ofconn *ofconn,
> return 0;
> }
>
> -static int
> +static enum ofperr
> handle_nxt_set_flow_format(struct ofconn *ofconn, const struct ofp_header *oh)
> {
> const struct nx_set_flow_format *msg
> @@ -2839,7 +2841,7 @@ handle_nxt_set_flow_format(struct ofconn *ofconn, const struct ofp_header *oh)
>
> format = ntohl(msg->format);
> if (format != NXFF_OPENFLOW10 && format != NXFF_NXM) {
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_EPERM);
> + return OFPERR_OFPBRC_EPERM;
> }
>
> if (format != ofconn_get_flow_format(ofconn)
> @@ -2852,7 +2854,7 @@ handle_nxt_set_flow_format(struct ofconn *ofconn, const struct ofp_header *oh)
> return 0;
> }
>
> -static int
> +static enum ofperr
> handle_barrier_request(struct ofconn *ofconn, const struct ofp_header *oh)
> {
> struct ofp_header *ob;
> @@ -2867,12 +2869,12 @@ handle_barrier_request(struct ofconn *ofconn, const struct ofp_header *oh)
> return 0;
> }
>
> -static int
> +static enum ofperr
> handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
> {
> const struct ofp_header *oh = msg->data;
> const struct ofputil_msg_type *type;
> - int error;
> + enum ofperr error;
>
> error = ofputil_decode_msg_type(oh, &type);
> if (error) {
> @@ -2966,9 +2968,9 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
> case OFPUTIL_NXST_AGGREGATE_REPLY:
> default:
> if (oh->type == OFPT_STATS_REQUEST || oh->type == OFPT_STATS_REPLY) {
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_STAT);
> + return OFPERR_OFPBRC_BAD_STAT;
> } else {
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE);
> + return OFPERR_OFPBRC_BAD_TYPE;
> }
> }
> }
> @@ -3114,8 +3116,7 @@ ofoperation_destroy(struct ofoperation *op)
> }
>
> /* Indicates that 'op' completed with status 'error', which is either 0 to
> - * indicate success or an OpenFlow error code (constructed with
> - * e.g. ofp_mkerr()).
> + * indicate success or an OpenFlow error code on failure.
> *
> * If 'error' is 0, indicating success, the operation will be committed
> * permanently to the flow table. There is one interesting subcase:
> @@ -3144,7 +3145,7 @@ ofoperation_destroy(struct ofoperation *op)
> * Please see the large comment in ofproto/ofproto-provider.h titled
> * "Asynchronous Operation Support" for more information. */
> void
> -ofoperation_complete(struct ofoperation *op, int error)
> +ofoperation_complete(struct ofoperation *op, enum ofperr error)
> {
> struct ofopgroup *group = op->group;
> struct rule *rule = op->rule;
> diff --git a/ofproto/pktbuf.c b/ofproto/pktbuf.c
> index fc4c66c..9382047 100644
> --- a/ofproto/pktbuf.c
> +++ b/ofproto/pktbuf.c
> @@ -152,8 +152,7 @@ pktbuf_get_null(void)
> }
>
> /* Attempts to retrieve a saved packet with the given 'id' from 'pb'. Returns
> - * 0 if successful, otherwise an OpenFlow error code constructed with
> - * ofp_mkerr().
> + * 0 if successful, otherwise an OpenFlow error code.
> *
> * On success, ordinarily stores the buffered packet in '*bufferp' and the
> * datapath port number on which the packet was received in '*in_port'. The
> @@ -167,13 +166,13 @@ pktbuf_get_null(void)
> * headroom.
> *
> * On failure, stores NULL in in '*bufferp' and UINT16_MAX in '*in_port'. */
> -int
> +enum ofperr
> pktbuf_retrieve(struct pktbuf *pb, uint32_t id, struct ofpbuf **bufferp,
> uint16_t *in_port)
> {
> static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 20);
> struct packet *p;
> - int error;
> + enum ofperr error;
>
> if (id == UINT32_MAX) {
> error = 0;
> @@ -183,7 +182,7 @@ pktbuf_retrieve(struct pktbuf *pb, uint32_t id, struct ofpbuf **bufferp,
> if (!pb) {
> VLOG_WARN_RL(&rl, "attempt to send buffered packet via connection "
> "without buffers");
> - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BUFFER_UNKNOWN);
> + return OFPERR_OFPBRC_BUFFER_UNKNOWN;
> }
>
> p = &pb->packets[id & PKTBUF_MASK];
> @@ -200,13 +199,13 @@ pktbuf_retrieve(struct pktbuf *pb, uint32_t id, struct ofpbuf **bufferp,
> } else {
> COVERAGE_INC(pktbuf_reuse_error);
> VLOG_WARN_RL(&rl, "attempt to reuse buffer %08"PRIx32, id);
> - error = ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BUFFER_EMPTY);
> + error = OFPERR_OFPBRC_BUFFER_EMPTY;
> }
> } else if (id >> PKTBUF_BITS != COOKIE_MAX) {
> COVERAGE_INC(pktbuf_buffer_unknown);
> VLOG_WARN_RL(&rl, "cookie mismatch: %08"PRIx32" != %08"PRIx32,
> id, (id & PKTBUF_MASK) | (p->cookie << PKTBUF_BITS));
> - error = ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BUFFER_UNKNOWN);
> + error = OFPERR_OFPBRC_BUFFER_UNKNOWN;
> } else {
> COVERAGE_INC(pktbuf_null_cookie);
> VLOG_INFO_RL(&rl, "Received null cookie %08"PRIx32" (this is normal "
> diff --git a/ofproto/pktbuf.h b/ofproto/pktbuf.h
> index 67f4973..80bf540 100644
> --- a/ofproto/pktbuf.h
> +++ b/ofproto/pktbuf.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2008, 2009 Nicira Networks.
> + * Copyright (c) 2008, 2009, 2011 Nicira Networks.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -19,6 +19,8 @@
>
> #include <stdint.h>
>
> +#include "ofp-errors.h"
> +
> struct pktbuf;
> struct ofpbuf;
>
> @@ -28,8 +30,8 @@ struct pktbuf *pktbuf_create(void);
> void pktbuf_destroy(struct pktbuf *);
> uint32_t pktbuf_save(struct pktbuf *, struct ofpbuf *buffer, uint16_t in_port);
> uint32_t pktbuf_get_null(void);
> -int pktbuf_retrieve(struct pktbuf *, uint32_t id, struct ofpbuf **bufferp,
> - uint16_t *in_port);
> +enum ofperr pktbuf_retrieve(struct pktbuf *, uint32_t id,
> + struct ofpbuf **bufferp, uint16_t *in_port);
> void pktbuf_discard(struct pktbuf *, uint32_t id);
>
> #endif /* pktbuf.h */
> diff --git a/tests/ofp-print.at b/tests/ofp-print.at
> index df5dc9b..7c32697 100644
> --- a/tests/ofp-print.at
> +++ b/tests/ofp-print.at
> @@ -16,9 +16,11 @@ AT_CLEANUP
>
> AT_SETUP([wrong OpenFlow version])
> AT_KEYWORDS([ofp-print])
> -AT_CHECK([ovs-ofctl ofp-print aabbccddeeff0011], [0], [dnl
> -Bad OpenFlow version 170:
> -00000000 aa bb cc dd ee ff 00 11- |........ |
> +AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print 00bb0008eeff0011],
> + [0], [dnl
> +***decode error: OFPBRC_BAD_TYPE***
> +00000000 00 bb 00 08 ee ff 00 11- |........ |
> +], [ofp_util|WARN|received OpenFlow message of unknown type 187
> ])
> AT_CLEANUP
>
> @@ -55,31 +57,66 @@ OFPT_HELLO (xid=0x0):
> ])
> AT_CLEANUP
>
> -AT_SETUP([OFPT_ERROR with type OFPET_HELLO_FAILED])
> +AT_SETUP([OFPT_ERROR with type OFPET_HELLO_FAILED - OF1.0])
> AT_KEYWORDS([ofp-print])
> AT_CHECK([ovs-ofctl ofp-print 010100170000000000000001657874726120646174610a], [0], [dnl
> -OFPT_ERROR (xid=0x0): type OFPET_HELLO_FAILED, code OFPHFC_EPERM
> +OFPT_ERROR (xid=0x0): OFPHFC_EPERM
> extra data\012
> ])
> AT_CLEANUP
>
> -AT_SETUP([OFPT_ERROR with type OFPET_BAD_REQUEST])
> +AT_SETUP([OFPT_ERROR with type OFPET_HELLO_FAILED - OF1.1])
> +AT_KEYWORDS([ofp-print])
> +AT_CHECK([ovs-ofctl ofp-print 020100170000000000000001657874726120646174610a], [0], [dnl
> +OFPT_ERROR (xid=0x0): OFPHFC_EPERM
> +extra data\012
> +])
> +AT_CLEANUP
> +
> +AT_SETUP([OFPT_ERROR with type OFPET_BAD_REQUEST - OF1.0])
> AT_KEYWORDS([ofp-print])
> AT_CHECK([ovs-ofctl ofp-print 01010014000000000001000601bbccddeeff0011], [0], [dnl
> -OFPT_ERROR (xid=0x0): type OFPET_BAD_REQUEST, code OFPBRC_BAD_LEN
> +OFPT_ERROR (xid=0x0): OFPBRC_BAD_LEN
> (***truncated to 8 bytes from 52445***)
> 00000000 01 bb cc dd ee ff 00 11- |........ |
> ])
> AT_CLEANUP
>
> -AT_SETUP([OFPT_ERROR with code NXBRC_NXM_BAD_PREREQ])
> +AT_SETUP([OFPT_ERROR with code NXBRC_NXM_BAD_PREREQ - OF1.0])
> AT_KEYWORDS([ofp-print])
> AT_CHECK([ovs-ofctl ofp-print '0101001c55555555 b0c20000 0000232000010104 0102000811111111'], [0], [dnl
> -OFPT_ERROR (xid=0x55555555): type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ
> +OFPT_ERROR (xid=0x55555555): NXBRC_NXM_BAD_PREREQ
> +OFPT_ECHO_REQUEST (xid=0x11111111): 0 bytes of payload
> +])
> +AT_CLEANUP
> +
> +AT_SETUP([OFPT_ERROR with code NXBRC_NXM_BAD_PREREQ - OF1.1])
> +AT_KEYWORDS([ofp-print])
> +AT_CHECK([ovs-ofctl ofp-print '0201001c55555555 b0c20000 0000232000010104 0102000811111111'], [0], [dnl
> +OFPT_ERROR (xid=0x55555555): NXBRC_NXM_BAD_PREREQ
> OFPT_ECHO_REQUEST (xid=0x11111111): 0 bytes of payload
> ])
> AT_CLEANUP
>
> +dnl Error type 3, code 1 is OFPFMFC_OVERLAP in OF1.0
> +dnl and OFPBIC_UNSUP_INST in OF1.1, so check that value in both versions.
> +AT_SETUP([OFPT_ERROR with type OFPFMFC_OVERLAP - OF1.0])
> +AT_KEYWORDS([ofp-print])
> +AT_CHECK([ovs-ofctl ofp-print 01010014000000000003000101bbccddeeff0011], [0], [dnl
> +OFPT_ERROR (xid=0x0): OFPFMFC_OVERLAP
> +(***truncated to 8 bytes from 52445***)
> +00000000 01 bb cc dd ee ff 00 11- |........ |
> +])
> +AT_CLEANUP
> +AT_SETUP([OFPT_ERROR with type OFPBIC_UNSUP_INST - OF1.1])
> +AT_KEYWORDS([ofp-print])
> +AT_CHECK([ovs-ofctl ofp-print 02010014000000000003000102bbccddeeff0011], [0], [dnl
> +OFPT_ERROR (xid=0x0): OFPBIC_UNSUP_INST
> +(***truncated to 8 bytes from 52445***)
> +00000000 02 bb cc dd ee ff 00 11- |........ |
> +])
> +AT_CLEANUP
> +
> AT_SETUP([OFPT_ECHO_REQUEST, empty payload])
> AT_KEYWORDS([ofp-print])
> AT_CHECK([ovs-ofctl ofp-print '01 02 00 08 00 00 00 01'], [0], [dnl
> @@ -180,7 +217,7 @@ ff fe 50 54 00 00 00 01 62 72 30 00 00 00 00 00 \
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
> 00 00 02 08 00 00 02 8f 00 00 02 8f \
> "], [0], [dnl
> -***decode error: type OFPET_BAD_REQUEST, code OFPBRC_BAD_LEN***
> +***decode error: OFPBRC_BAD_LEN***
> 00000000 01 06 00 dc 00 00 00 01-00 00 50 54 00 00 00 01 |..........PT....|
> 00000010 00 00 01 00 02 00 00 00-00 00 00 87 00 00 0f ff |................|
> 00000020 ff fe 50 54 00 00 00 01-62 72 30 00 00 00 00 00 |..PT....br0.....|
> diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
> index 2a458c8..acf5809 100644
> --- a/tests/ovs-ofctl.at
> +++ b/tests/ovs-ofctl.at
> @@ -390,7 +390,7 @@ NXM_OF_IN_PORT(0012), NXM_OF_ETH_TYPE(0800)
>
> # vlan tci
> NXM_OF_VLAN_TCI(f009)
> -nx_pull_match() returned error 44010105 (type OFPET_BAD_REQUEST, code NXBRC_NXM_DUP_TYPE)
> +nx_pull_match() returned error NXBRC_NXM_DUP_TYPE
> NXM_OF_VLAN_TCI(0000)
> NXM_OF_VLAN_TCI(3123)
> NXM_OF_VLAN_TCI(0123)
> @@ -400,114 +400,114 @@ NXM_OF_VLAN_TCI_W(0000/e000)
>
> # IP TOS
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_TOS(f0)
> -nx_pull_match() returned error 44010102 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_VALUE)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_VALUE
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # IP ECN
> NXM_OF_ETH_TYPE(0800), NXM_NX_IP_ECN(03)
> -nx_pull_match() returned error 44010102 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_VALUE)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_VALUE
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # IP protocol
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(01)
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(05)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # IP TTL
> NXM_OF_ETH_TYPE(0800), NXM_NX_IP_TTL(80)
> NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_TTL(ff)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # IP source
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_SRC(ac100014)
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_SRC_W(c0a80000/ffff0000)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # IP destination
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_DST(ac100014)
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_DST_W(c0a80000/ffff0000)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # TCP source port
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_SRC(4231)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # TCP destination port
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_DST(4231)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # UDP source port
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_SRC(8732)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # UDP destination port
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_DST(1782)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # ICMP type
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(01), NXM_OF_ICMP_TYPE(12)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # ICMP code
> NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(01), NXM_OF_ICMP_CODE(12)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # ARP opcode
> NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_OP(0001)
> -nx_pull_match() returned error 44010102 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_VALUE)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010105 (type OFPET_BAD_REQUEST, code NXBRC_NXM_DUP_TYPE)
> +nx_pull_match() returned error NXBRC_NXM_BAD_VALUE
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_DUP_TYPE
>
> # ARP source protocol address
> NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_SPA(ac100014)
> NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_SPA_W(c0a81200/ffffff00)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # ARP destination protocol address
> NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_TPA(ac100014)
> NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_TPA_W(c0a81200/ffffff00)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # ARP source hardware address
> NXM_OF_ETH_TYPE(0806), NXM_NX_ARP_SHA(0002e30f80a4)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # ARP destination hardware address
> NXM_OF_ETH_TYPE(0806), NXM_NX_ARP_THA(0002e30f80a4)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # IPv6 source
> NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC(20010db83c4d00010002000300040005)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC_W(20010db83c4d00010000000000000000/ffffffffffffffff0000000000000000)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # IPv6 destination
> NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_DST(20010db83c4d00010002000300040005)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_DST_W(20010db83c4d00010000000000000000/ffffffffffffffff0000000000000000)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # ND source hardware address
> NXM_OF_ETH_TYPE(86dd), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(87), NXM_NX_ND_TARGET(20010db83c4d00010002000300040005), NXM_NX_ND_SLL(0002e30f80a4)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # ND destination hardware address
> NXM_OF_ETH_TYPE(86dd), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(88), NXM_NX_ND_TARGET(20010db83c4d00010002000300040005), NXM_NX_ND_TLL(0002e30f80a4)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> -nx_pull_match() returned error 44010104 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_PREREQ)
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
> +nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
>
> # IPv4 fragments.
> NXM_OF_ETH_TYPE(0800), NXM_NX_IP_FRAG(00)
> @@ -520,7 +520,7 @@ NXM_OF_ETH_TYPE(0800), NXM_NX_IP_FRAG_W(00/02)
> NXM_OF_ETH_TYPE(0800), NXM_NX_IP_FRAG_W(01/01)
> NXM_OF_ETH_TYPE(0800), NXM_NX_IP_FRAG_W(02/02)
> NXM_OF_ETH_TYPE(0800), NXM_NX_IP_FRAG(03)
> -nx_pull_match() returned error 44010102 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_VALUE)
> +nx_pull_match() returned error NXBRC_NXM_BAD_VALUE
>
> # IPv6 fragments.
> NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_FRAG(00)
> @@ -533,7 +533,7 @@ NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_FRAG_W(00/02)
> NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_FRAG_W(01/01)
> NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_FRAG_W(02/02)
> NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_FRAG(03)
> -nx_pull_match() returned error 44010102 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_VALUE)
> +nx_pull_match() returned error NXBRC_NXM_BAD_VALUE
>
> # Tunnel ID.
> NXM_NX_TUN_ID(00000000abcdef01)
> @@ -544,7 +544,7 @@ NXM_NX_REG0(acebdf56)
> NXM_NX_REG0_W(a0e0d050/f0f0f0f0)
>
> # Invalid field number.
> -nx_pull_match() returned error 44010101 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_TYPE)
> +nx_pull_match() returned error NXBRC_NXM_BAD_TYPE
>
> # Unimplemented registers.
> #
> @@ -552,8 +552,8 @@ nx_pull_match() returned error 44010101 (type OFPET_BAD_REQUEST, code NXBRC_NXM_
> # registers are implemented.
> NXM_NX_REG0(12345678)
> NXM_NX_REG0_W(12345678/12345678)
> -nx_pull_match() returned error 44010101 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_TYPE)
> -nx_pull_match() returned error 44010101 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_TYPE)
> +nx_pull_match() returned error NXBRC_NXM_BAD_TYPE
> +nx_pull_match() returned error NXBRC_NXM_BAD_TYPE
> ])
> AT_CLEANUP
>
> diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
> index cf77300..bd184b8 100644
> --- a/utilities/ovs-ofctl.c
> +++ b/utilities/ovs-ofctl.c
> @@ -36,6 +36,7 @@
> #include "netlink.h"
> #include "nx-match.h"
> #include "odp-util.h"
> +#include "ofp-errors.h"
> #include "ofp-parse.h"
> #include "ofp-print.h"
> #include "ofp-util.h"
> @@ -1455,8 +1456,8 @@ do_parse_nx_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
> while (!ds_get_line(&in, stdin)) {
> struct ofpbuf nx_match;
> struct cls_rule rule;
> + enum ofperr error;
> int match_len;
> - int error;
> char *s;
>
> /* Delete comments, skip blank lines. */
> @@ -1492,8 +1493,8 @@ do_parse_nx_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
> puts(out);
> free(out);
> } else {
> - printf("nx_pull_match() returned error %x (%s)\n", error,
> - ofputil_error_to_string(error));
> + printf("nx_pull_match() returned error %s\n",
> + ofperr_get_name(error));
> }
>
> ofpbuf_uninit(&nx_match);
> --
> 1.7.2.5
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
More information about the dev
mailing list