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
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():
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:
};
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;
/dhparams.c
/dirs.c
/coverage-counters.c
-/ofp-errors.c
+/ofp-errors.inc
> 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:
#include "flow.h"
#include "nx-match.h"
+#include "ofp-errors.h"
#include "ofp-util.h"
#include "openflow/nicira-ext.h"
#include "vlog.h"
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);
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);
#define AUTOPATH_H 1
#include <stdint.h>
+#include "ofp-errors.h"
struct flow;
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 */
-/* 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.
#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"
/* 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)
{
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);
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) {
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) {
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);
}
"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;
* 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;
}
}
#include <stddef.h>
#include <stdint.h>
+#include "ofp-errors.h"
#include "openflow/nicira-ext.h"
#include "openvswitch/types.h"
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 *);
#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"
{
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));
}
}
#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"
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;
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;
/* 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;
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);
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;
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)
}
}
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;
{
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;
/* 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);
}
int dst_ofs;
const struct mf_field *dst_field;
- int error;
+ enum ofperr error;
int i;
if (!header) {
}
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,
#ifndef LEARN_H
#define LEARN_H 1
+#include "ofp-errors.h"
+
struct ds;
struct flow;
struct ofpbuf;
* 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 *);
#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"
#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"
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
\f
/* 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) {
return 0;
}
- return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
+ return OFPERR_OFPBAC_BAD_ARGUMENT;
}
\f
/* multipath_execute(). */
/*
- * 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.
#define MULTIPATH_H 1
#include <stdint.h>
+#include "ofp-errors.h"
struct ds;
struct flow;
* 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 *);
/*
- * 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.
#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"
* 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
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)
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);
(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);
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);
/* 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;
}
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
* 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)
/* 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)
/* 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)
{
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)
{
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) {
/* 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;
/*
- * 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.
#include <sys/types.h>
#include <netinet/in.h>
#include "openvswitch/types.h"
+#include "ofp-errors.h"
struct cls_rule;
struct ds;
* 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);
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 *);
--- /dev/null
+#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);
+}
/*
- * 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.
#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 */
#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"
#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
{
struct ofputil_flow_mod fm;
bool need_priority;
- int error;
+ enum ofperr error;
error = ofputil_decode_flow_mod(&fm, oh, true);
if (error) {
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) {
}
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
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;
}
}
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) {
} 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",
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) {
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) {
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;
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;
"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)
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)
{
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;
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)) {
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;
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;
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)
{
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) {
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)
{
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) {
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)
{
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) {
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)
{
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) {
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)
{
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 },
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);
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) {
/* 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;
}
* 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)
{
/* 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);
} 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);
/* 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);
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)
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));
return error;
}
if (b.size) {
- return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
+ return OFPERR_OFPBRC_BAD_LEN;
}
fsr->aggregate = aggregate;
/* 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)
{
/* 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)
{
return error;
}
if (b.size) {
- return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
+ return OFPERR_OFPBRC_BAD_LEN;
}
fr->cookie = nfr->cookie;
}
if (!ofpbuf_try_pull(&b, 2)) {
- return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
+ return OFPERR_OFPBRC_BAD_LEN;
}
pin->packet = b.data;
/* 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) {
if (port < max_ports) {
return 0;
}
- return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT);
+ return OFPERR_OFPBAC_BAD_OUT_PORT;
}
}
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)
{
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;
}
}
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)
{
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;
}
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;
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;
}
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;
}
};
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)
}
/* 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
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;
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_*
}
}
-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.
*
* 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)
{
error:
*actionsp = NULL;
*n_actionsp = 0;
- return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
+ return OFPERR_OFPBRC_BAD_LEN;
}
bool
};
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 *);
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);
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);
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);
((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);
-\f
-/* 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
-};
-\f
-/* 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);
/*
- * 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.
#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"
static void
vcs_send_error(struct vconn *vconn)
{
- struct ofp_error_msg *error;
struct ofpbuf *b;
char s[128];
int retval;
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);
}
}
-/* 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,
? 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)
{
#include "hmap.h"
#include "list.h"
+#include "ofp-errors.h"
#include "ofproto.h"
#include "openflow/nicira-ext.h"
#include "openvswitch/types.h"
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 *);
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);
}
}
-static int
+static enum ofperr
rule_execute(struct rule *rule_, const struct flow *flow,
struct ofpbuf *packet)
{
{
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);
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);
}
}
-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,
#include "cfm.h"
#include "classifier.h"
#include "list.h"
+#include "ofp-errors.h"
#include "shash.h"
#include "timeval.h"
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.
*
* 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
/* 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
* 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).
*
*
* * 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.
*
* 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);
*
* 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
*
* 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
* '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 ## */
*
* 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 *,
#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"
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);
}
/* 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
return rule->cr.priority > UINT16_MAX;
}
\f
-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);
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);
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);
}
/* 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);
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);
* 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. */
}
}
-static int
+static enum ofperr
handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh)
{
struct ofproto *p = ofconn_get_ofproto(ofconn);
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) {
return 0;
}
-static int
+static enum ofperr
handle_desc_stats_request(struct ofconn *ofconn,
const struct ofp_stats_msg *request)
{
return 0;
}
-static int
+static enum ofperr
handle_table_stats_request(struct ofconn *ofconn,
const struct ofp_stats_msg *request)
{
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)
{
/* 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);
}
* 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) {
* 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,
return 0;
}
-static int
+static enum ofperr
handle_flow_stats_request(struct ofconn *ofconn,
const struct ofp_stats_msg *osm)
{
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) {
: -1);
}
-static int
+static enum ofperr
handle_aggregate_stats_request(struct ofconn *ofconn,
const struct ofp_stats_msg *osm)
{
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) {
}
}
-static int
+static enum ofperr
handle_queue_stats_request(struct ofconn *ofconn,
const struct ofp_queue_stats_request *qsr)
{
}
} 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);
*
* 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)
{
} 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. */
* 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)
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)
}
/* 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)
/* 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)
{
}
/* 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,
}
/* 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,
ofopgroup_submit(group);
}
\f
-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) {
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)
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;
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
return 0;
}
-static int
+static enum ofperr
handle_nxt_flow_mod_table_id(struct ofconn *ofconn,
const struct ofp_header *oh)
{
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
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)
return 0;
}
-static int
+static enum ofperr
handle_nxt_set_packet_in_format(struct ofconn *ofconn,
const struct ofp_header *oh)
{
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)
return 0;
}
-static int
+static enum ofperr
handle_barrier_request(struct ofconn *ofconn, const struct ofp_header *oh)
{
struct ofp_header *ob;
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) {
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;
}
}
}
}
/* 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:
* 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;
assert(rule->pending == op);
assert(op->status < 0);
- assert(error >= 0);
if (!error
&& !group->error
}
/* 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
* 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;
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];
} 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 "
/*
- * 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.
#include <stddef.h>
#include <stdint.h>
+#include "ofp-errors.h"
+
struct pktbuf;
struct ofpbuf;
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 */
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
])
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
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.....|
# 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)
# 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)
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)
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)
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.
#
# 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
])
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
#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"
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. */
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);