diff options
-rwxr-xr-x | build-aux/extract-ofp-errors | 243 | ||||
-rw-r--r-- | include/openflow/openflow.h | 77 | ||||
-rw-r--r-- | lib/.gitignore | 2 | ||||
-rw-r--r-- | lib/automake.mk | 13 | ||||
-rw-r--r-- | lib/autopath.c | 5 | ||||
-rw-r--r-- | lib/autopath.h | 4 | ||||
-rw-r--r-- | lib/bundle.c | 24 | ||||
-rw-r--r-- | lib/bundle.h | 5 | ||||
-rw-r--r-- | lib/dpif.c | 10 | ||||
-rw-r--r-- | lib/learn.c | 27 | ||||
-rw-r--r-- | lib/learn.h | 4 | ||||
-rw-r--r-- | lib/learning-switch.c | 1 | ||||
-rw-r--r-- | lib/multipath.c | 7 | ||||
-rw-r--r-- | lib/multipath.h | 6 | ||||
-rw-r--r-- | lib/nx-match.c | 56 | ||||
-rw-r--r-- | lib/nx-match.h | 25 | ||||
-rw-r--r-- | lib/ofp-errors.c | 287 | ||||
-rw-r--r-- | lib/ofp-errors.h | 389 | ||||
-rw-r--r-- | lib/ofp-print.c | 40 | ||||
-rw-r--r-- | lib/ofp-util.c | 367 | ||||
-rw-r--r-- | lib/ofp-util.h | 174 | ||||
-rw-r--r-- | lib/vconn.c | 11 | ||||
-rw-r--r-- | ofproto/connmgr.c | 21 | ||||
-rw-r--r-- | ofproto/connmgr.h | 7 | ||||
-rw-r--r-- | ofproto/ofproto-dpif.c | 19 | ||||
-rw-r--r-- | ofproto/ofproto-provider.h | 49 | ||||
-rw-r--r-- | ofproto/ofproto.c | 150 | ||||
-rw-r--r-- | ofproto/pktbuf.c | 13 | ||||
-rw-r--r-- | ofproto/pktbuf.h | 8 | ||||
-rw-r--r-- | tests/ofp-print.at | 57 | ||||
-rw-r--r-- | tests/ovs-ofctl.at | 94 | ||||
-rw-r--r-- | utilities/ovs-ofctl.c | 7 |
32 files changed, 1277 insertions, 925 deletions
diff --git a/build-aux/extract-ofp-errors b/build-aux/extract-ofp-errors index c34888fc..5c3cd26f 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 f2609840..f68a140b 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 c5b6cac9..6cbaf304 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 7153e930..4e2fcf3b 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -278,13 +278,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 9a39c6a1..321b106d 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 98b02b41..19e2d073 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 5db97d39..8e98fb57 100644 --- a/lib/bundle.c +++ b/lib/bundle.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 Nicira Networks. +/* Copyright (c) 2011, 2012 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -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 if (!error) { error = nxm_dst_check(nab->dst, ofs, n_bits, flow); } @@ -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 12497f78..580ecf81 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 *); @@ -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" @@ -1200,13 +1201,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 9d97cb35..241f3d1f 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 19a9089c..b83bee20 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 2fc6392f..3bcb9610 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 f68dafdc..80d801d6 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 8ac4bfd3..3c4ff450 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 eaccce12..63e5e5be 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011 Nicira Networks. + * Copyright (c) 2010, 2011, 2012 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -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; } -static int +static enum ofperr nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict, uint16_t priority, struct cls_rule *rule, ovs_be64 *cookie, ovs_be64 *cookie_mask) @@ -111,7 +102,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict, 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); @@ -122,26 +113,26 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict, (header = nx_entry_ok(p, match_len)) != 0; p += 4 + NXM_LENGTH(header), match_len -= 4 + NXM_LENGTH(header)) { const struct mf_field *mf; - int error; + enum ofperr error; mf = mf_from_nxm_header(header); if (!mf) { if (strict) { - error = NXM_BAD_TYPE; + error = OFPERR_NXBRC_NXM_BAD_TYPE; } else { continue; } } 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); @@ -150,7 +141,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict, 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); @@ -161,7 +152,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict, /* Check if the match is for a cookie rather than a classifier rule. */ if ((header == NXM_NX_COOKIE || header == NXM_NX_COOKIE_W) && cookie) { if (*cookie_mask) { - error = NXM_DUP_TYPE; + error = OFPERR_NXBRC_NXM_DUP_TYPE; } else { unsigned int width = sizeof *cookie; @@ -176,20 +167,17 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict, } 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; } } - return match_len ? NXM_INVALID : 0; + return match_len ? OFPERR_NXBRC_NXM_INVALID : 0; } /* Parses the nx_match formatted match description in 'b' with length @@ -201,7 +189,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict, * Fails with an error when encountering unknown NXM headers. * * Returns 0 if successful, otherwise an OpenFlow error code. */ -int +enum ofperr nx_pull_match(struct ofpbuf *b, unsigned int match_len, uint16_t priority, struct cls_rule *rule, ovs_be64 *cookie, ovs_be64 *cookie_mask) @@ -212,7 +200,7 @@ nx_pull_match(struct ofpbuf *b, unsigned int match_len, /* Behaves the same as nx_pull_match() with one exception. Skips over unknown * NXM headers instead of failing with an error when they are encountered. */ -int +enum ofperr nx_pull_match_loose(struct ofpbuf *b, unsigned int match_len, uint16_t priority, struct cls_rule *rule, ovs_be64 *cookie, ovs_be64 *cookie_mask) @@ -992,7 +980,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) { @@ -1007,12 +995,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) { @@ -1029,16 +1017,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) { @@ -1048,7 +1036,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 8931d58a..c1892873 100644 --- a/lib/nx-match.h +++ b/lib/nx-match.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011 Nicira Networks. + * Copyright (c) 2010, 2011, 2012 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -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,11 +35,12 @@ 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 *, ovs_be64 *cookie, ovs_be64 *cookie_mask); -int nx_pull_match_loose(struct ofpbuf *, unsigned int match_len, - uint16_t priority, struct cls_rule *, - ovs_be64 *cookie, ovs_be64 *cookie_mask); +enum ofperr nx_pull_match(struct ofpbuf *, unsigned int match_len, + uint16_t priority, struct cls_rule *, + ovs_be64 *cookie, ovs_be64 *cookie_mask); +enum ofperr nx_pull_match_loose(struct ofpbuf *, unsigned int match_len, + uint16_t priority, struct cls_rule *, + ovs_be64 *cookie, ovs_be64 *cookie_mask); int nx_put_match(struct ofpbuf *, const struct cls_rule *, ovs_be64 cookie, ovs_be64 cookie_mask); @@ -55,11 +57,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 00000000..028475e1 --- /dev/null +++ b/lib/ofp-errors.c @@ -0,0 +1,287 @@ +#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; + size_t ofs; + + 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; + } + + ofs = error - OFPERR_OFS; + pair = &domain->errors[ofs]; + 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 d677b5d4..fbd28e3b 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 89267d87..aff12b6e 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 @@ -746,7 +747,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) { @@ -845,7 +846,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) { @@ -896,14 +897,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 @@ -912,32 +911,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; } } @@ -976,7 +969,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) { @@ -1467,9 +1460,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", @@ -1480,7 +1470,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 a00939dc..b20d3fb6 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) { @@ -389,7 +389,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; @@ -399,14 +399,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)) { @@ -416,7 +416,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; @@ -424,7 +424,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; @@ -434,27 +434,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) { @@ -471,11 +471,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) { @@ -487,7 +487,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) { @@ -504,11 +504,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) { @@ -520,20 +520,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) { @@ -570,11 +570,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) { @@ -590,7 +590,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) { @@ -627,11 +627,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) { @@ -646,7 +646,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) { @@ -655,7 +655,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 }, @@ -735,10 +735,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); @@ -762,22 +762,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) { @@ -791,18 +790,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; } @@ -1005,7 +1003,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) { @@ -1020,7 +1018,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); @@ -1054,7 +1052,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); @@ -1075,7 +1073,7 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm, /* The "NXM_NX_COOKIE*" matches are not valid for flow * additions. Additions must use the "cookie" field of * the "nx_flow_mod" structure. */ - return ofp_mkerr(OFPET_BAD_REQUEST, NXBRC_NXM_INVALID); + return OFPERR_NXBRC_NXM_INVALID; } else { fm->cookie = nfm->cookie; fm->cookie_mask = htonll(UINT64_MAX); @@ -1165,7 +1163,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) @@ -1182,14 +1180,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)); @@ -1200,7 +1198,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; @@ -1213,7 +1211,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) { @@ -1499,7 +1497,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) { @@ -1535,7 +1533,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; @@ -1637,7 +1635,7 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin, } if (!ofpbuf_try_pull(&b, 2)) { - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); + return OFPERR_OFPBRC_BAD_LEN; } pin->packet = b.data; @@ -2225,8 +2223,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) { @@ -2243,7 +2241,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; } } @@ -2309,16 +2307,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) { @@ -2326,7 +2324,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; } } @@ -2334,7 +2332,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) { @@ -2342,20 +2340,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; } @@ -2369,13 +2363,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; @@ -2383,7 +2377,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; @@ -2446,17 +2440,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; } @@ -2468,11 +2460,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) @@ -2523,8 +2515,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 @@ -2544,7 +2536,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; @@ -2556,7 +2548,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_* @@ -2783,207 +2775,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. * @@ -2995,7 +2786,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) { @@ -3019,7 +2810,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 13195c76..d01e17a5 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -90,15 +90,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 *); @@ -151,8 +152,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); @@ -167,8 +169,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); @@ -215,8 +217,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); @@ -418,160 +420,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 6ea93667..8e6374e7 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 46d6d796..28d9488d 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -844,24 +844,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, @@ -870,17 +868,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 0df840b5..bbee7f4f 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" @@ -97,10 +98,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 60f81755..15532e02 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -3872,14 +3872,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); @@ -3956,7 +3956,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) { @@ -3987,7 +3987,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); @@ -4535,9 +4535,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); @@ -5521,16 +5520,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 6c8583ea..b9958318 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 07d4934b..29259e40 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,14 +2081,14 @@ 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, ovs_be64 cookie, ovs_be64 cookie_mask, uint16_t out_port, struct list *rules) { struct classifier *cls; - int error; + enum ofperr error; error = check_table_id(ofproto, table_id); if (error) { @@ -2123,7 +2125,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, ovs_be64 cookie, ovs_be64 cookie_mask, @@ -2155,7 +2157,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) { @@ -2164,7 +2166,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) { @@ -2284,7 +2286,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) { @@ -2295,7 +2297,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) { @@ -2392,7 +2394,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) { @@ -2419,7 +2421,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); @@ -2451,12 +2453,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) { @@ -2488,13 +2490,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. */ @@ -2558,7 +2560,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) @@ -2586,12 +2588,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) @@ -2608,11 +2610,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) @@ -2635,7 +2637,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) { @@ -2656,13 +2658,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->cookie, fm->cookie_mask, @@ -2674,13 +2676,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->cookie, fm->cookie_mask, @@ -2734,11 +2736,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) { @@ -2756,13 +2758,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) @@ -2793,11 +2795,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; @@ -2806,13 +2808,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 @@ -2829,7 +2831,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) { @@ -2840,7 +2842,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 @@ -2849,7 +2851,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) @@ -2862,7 +2864,7 @@ handle_nxt_set_flow_format(struct ofconn *ofconn, const struct ofp_header *oh) return 0; } -static int +static enum ofperr handle_nxt_set_packet_in_format(struct ofconn *ofconn, const struct ofp_header *oh) { @@ -2872,7 +2874,7 @@ handle_nxt_set_packet_in_format(struct ofconn *ofconn, msg = (const struct nx_set_packet_in_format *) oh; format = ntohl(msg->format); if (format != NXFF_OPENFLOW10 && format != NXPIF_NXM) { - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_EPERM); + return OFPERR_OFPBRC_EPERM; } if (format != ofconn_get_packet_in_format(ofconn) @@ -2885,7 +2887,7 @@ handle_nxt_set_packet_in_format(struct ofconn *ofconn, return 0; } -static int +static enum ofperr handle_barrier_request(struct ofconn *ofconn, const struct ofp_header *oh) { struct ofp_header *ob; @@ -2900,12 +2902,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) { @@ -3003,9 +3005,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; } } } @@ -3151,8 +3153,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: @@ -3181,7 +3182,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; @@ -3190,7 +3191,6 @@ ofoperation_complete(struct ofoperation *op, int error) assert(rule->pending == op); assert(op->status < 0); - assert(error >= 0); if (!error && !group->error diff --git a/ofproto/pktbuf.c b/ofproto/pktbuf.c index 7cc96a5c..23c01e03 100644 --- a/ofproto/pktbuf.c +++ b/ofproto/pktbuf.c @@ -155,8 +155,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 @@ -170,13 +169,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; @@ -186,7 +185,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]; @@ -203,13 +202,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 82d7a85b..e29117ab 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. @@ -20,6 +20,8 @@ #include <stddef.h> #include <stdint.h> +#include "ofp-errors.h" + struct pktbuf; struct ofpbuf; @@ -30,8 +32,8 @@ void pktbuf_destroy(struct pktbuf *); uint32_t pktbuf_save(struct pktbuf *, const void *buffer, size_t buffer_size, 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 2ca07c46..0619e986 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 57712c06..0b58b3da 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -394,7 +394,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) @@ -404,114 +404,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) @@ -524,7 +524,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) @@ -537,7 +537,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 # Flow cookie. NXM_NX_COOKIE(00000000abcdef01) @@ -552,7 +552,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. # @@ -560,8 +560,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 @@ -572,7 +572,7 @@ NXM_OF_IN_PORT(0001), 01020304(1111/2222), NXM_OF_ETH_TYPE(0800) ]) AT_CHECK([ovs-ofctl --strict parse-nx-match < nx-match.txt], [0], [dnl -nx_pull_match() returned error 44010101 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_TYPE) +nx_pull_match() returned error NXBRC_NXM_BAD_TYPE ]) AT_CHECK([ovs-ofctl parse-nx-match < nx-match.txt], [0], [dnl diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 995a6c6c..6219f94a 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -37,6 +37,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" @@ -1562,8 +1563,8 @@ do_parse_nx_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) struct ofpbuf nx_match; struct cls_rule rule; ovs_be64 cookie, cookie_mask; + enum ofperr error; int match_len; - int error; char *s; /* Delete comments, skip blank lines. */ @@ -1606,8 +1607,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); |