token = None
return False
-def fatal(msg):
+n_errors = 0
+def error(msg):
+ global n_errors
sys.stderr.write("%s:%d: %s\n" % (fileName, lineNumber, msg))
+ n_errors += 1
+
+def fatal(msg):
+ error(msg)
sys.exit(1)
def skipDirective():
names = []
domain = {}
reverse = {}
- for domain_name in ("OF1.0", "OF1.1", "NX1.0", "NX1.1"):
+ for domain_name in ("OF1.0", "OF1.1", "OF1.2", "NX1.0", "NX1.1"):
domain[domain_name] = {}
reverse[domain_name] = {}
+ n_errors = 0
+ expected_errors = {}
+
global fileName
for fileName in filenames:
global inputFile
elif re.match('}', line):
break
- m = re.match('\s+/\* ((?:.(?!\. ))+.)\. (.*)$', line)
- if not m:
+ if not line.lstrip().startswith('/*'):
fatal("unexpected syntax between errors")
- dsts, comment = m.groups()
-
- comment.rstrip()
+ comment = line.lstrip()[2:].strip()
while not comment.endswith('*/'):
getLine()
if line.startswith('/*') or not line or line.isspace():
comment += ' %s' % line.lstrip('* \t').rstrip(' \t\r\n')
comment = comment[:-2].rstrip()
+ m = re.match('Expected: (.*)\.$', comment)
+ if m:
+ expected_errors[m.group(1)] = (fileName, lineNumber)
+ continue
+
+ m = re.match('((?:.(?!\. ))+.)\. (.*)$', comment)
+ if not m:
+ fatal("unexpected syntax between errors")
+
+ dsts, comment = m.groups()
+
getLine()
m = re.match('\s+(?:OFPERR_((?:OFP|NX)[A-Z0-9_]+))(\s*=\s*OFPERR_OFS)?,',
line)
names.append(enum)
for dst in dsts.split(', '):
- m = re.match(r'([A-Z0-9.+]+)\((\d+)(?:,(\d+))?\)$', dst)
+ m = re.match(r'([A-Z0-9.+]+)\((\d+|(0x)[0-9a-fA-F]+)(?:,(\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))
+ base = 16
+ else:
+ base = 10
+ type_ = int(m.group(2), base)
+ if m.group(4):
+ code = int(m.group(4))
else:
code = None
- target_map = {"OF1.0+": ("OF1.0", "OF1.1"),
- "OF1.1+": ("OF1.1",),
+ target_map = {"OF1.0+": ("OF1.0", "OF1.1", "OF1.2"),
+ "OF1.1+": ("OF1.1", "OF1.2"),
+ "OF1.2+": ("OF1.2",),
"OF1.0": ("OF1.0",),
"OF1.1": ("OF1.1",),
- "NX1.0+": ("OF1.0", "OF1.1"),
+ "OF1.2": ("OF1.2",),
+ "NX1.0+": ("OF1.0", "OF1.1", "OF1.2"),
"NX1.0": ("OF1.0",),
- "NX1.1": ("OF1.1",)}
+ "NX1.1": ("OF1.1",),
+ "NX1.2": ("OF1.2",)}
if targets not in target_map:
fatal("%s: unknown error domain" % targets)
for target in target_map[targets]:
- if type_ not in domain[target]:
- domain[target][type_] = {}
+ domain[target].setdefault(type_, {})
if code in domain[target][type_]:
- fatal("%s: duplicate assignment in domain" % dst)
- domain[target][type_][code] = enum
+ msg = "%d,%d in %s means both %s and %s" % (
+ type_, code, target,
+ domain[target][type_][code][0], enum)
+ if msg in expected_errors:
+ del expected_errors[msg]
+ else:
+ error("%s: %s." % (dst, msg))
+ sys.stderr.write("%s:%d: %s: Here is the location "
+ "of the previous definition.\n"
+ % (domain[target][type_][code][1],
+ domain[target][type_][code][2],
+ dst))
+ else:
+ domain[target][type_][code] = (enum, fileName,
+ lineNumber)
+
+ if enum in reverse[target]:
+ error("%s: %s in %s means both %d,%d and %d,%d." %
+ (dst, enum, target,
+ reverse[target][enum][0],
+ reverse[target][enum][1],
+ type_, code))
reverse[target][enum] = (type_, code)
inputFile.close()
+ for fn, ln in expected_errors.itervalues():
+ sys.stderr.write("%s:%d: expected duplicate not used.\n" % (fn, ln))
+ n_errors += 1
+
+ if n_errors:
+ sys.exit(1)
+
print """\
/* Generated automatically; do not modify! -*- buffer-read-only: t -*- */
%s_decode(uint16_t type, uint16_t code)
{
switch ((type << 16) | code) {""" % name
+ found = set()
for enum in names:
if enum not in map:
continue
type_, code = map[enum]
if code is None:
continue
+ value = (type_ << 16) | code
+ if value in found:
+ continue
+ found.add(value)
print " case (%d << 16) | %d:" % (type_, code)
print " return OFPERR_%s;" % enum
print """\
output_domain(reverse["OF1.0"], "ofperr_of10", "OpenFlow 1.0", 0x01)
output_domain(reverse["OF1.1"], "ofperr_of11", "OpenFlow 1.1", 0x02)
+ output_domain(reverse["OF1.2"], "ofperr_of12", "OpenFlow 1.2", 0x03)
if __name__ == '__main__':
if '--help' in sys.argv:
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 OFPERR_OFPBRC_BAD_LEN;
+ return OFPERR_OFPBMC_BAD_LEN;
}
cls_rule_init_catchall(rule, priority);
mf = mf_from_nxm_header(header);
if (!mf) {
if (strict) {
- error = OFPERR_NXBRC_NXM_BAD_TYPE;
+ error = OFPERR_OFPBMC_BAD_FIELD;
} else {
continue;
}
} else if (!mf_are_prereqs_ok(mf, &rule->flow)) {
- error = OFPERR_NXBRC_NXM_BAD_PREREQ;
+ error = OFPERR_OFPBMC_BAD_PREREQ;
} else if (!mf_is_all_wild(mf, &rule->wc)) {
- error = OFPERR_NXBRC_NXM_DUP_TYPE;
+ error = OFPERR_OFPBMC_DUP_FIELD;
} else {
unsigned int width = mf->n_bytes;
union mf_value value;
memcpy(&value, p + 4, width);
if (!mf_is_value_valid(mf, &value)) {
- error = OFPERR_NXBRC_NXM_BAD_VALUE;
+ error = OFPERR_OFPBMC_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 = OFPERR_NXBRC_NXM_BAD_MASK;
+ error = OFPERR_OFPBMC_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 = OFPERR_NXBRC_NXM_DUP_TYPE;
+ error = OFPERR_OFPBMC_DUP_FIELD;
} else {
unsigned int width = sizeof *cookie;
}
}
- return match_len ? OFPERR_NXBRC_NXM_INVALID : 0;
+ return match_len ? OFPERR_OFPBMC_BAD_LEN : 0;
}
/* Parses the nx_match formatted match description in 'b' with length
{
return (version == ofperr_of10.version ? &ofperr_of10
: version == ofperr_of11.version ? &ofperr_of11
+ : version == ofperr_of12.version ? &ofperr_of12
: NULL);
}
+/* Returns the name (e.g. "OpenFlow 1.0") of OpenFlow error domain 'domain'. */
+const char *
+ofperr_domain_get_name(const struct ofperr_domain *domain)
+{
+ return domain->name;
+}
+
/* Returns true if 'error' is a valid OFPERR_* value, false otherwise. */
bool
ofperr_is_valid(enum ofperr error)
: "<invalid>");
}
+/* Returns the OFPERR_* value that corresponds for 'name', 0 if none exists.
+ * For example, returns OFPERR_OFPHFC_INCOMPATIBLE if 'name' is
+ * "OFPHFC_INCOMPATIBLE".
+ *
+ * This is probably useful only for debugging and testing. */
+enum ofperr
+ofperr_from_name(const char *name)
+{
+ int i;
+
+ for (i = 0; i < OFPERR_N_ERRORS; i++) {
+ if (!strcmp(name, error_names[i])) {
+ return i + OFPERR_OFS;
+ }
+ }
+ return 0;
+}
+
/* 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. */
: "<invalid>");
}
+static const struct pair *
+ofperr_get_pair__(enum ofperr error, const struct ofperr_domain *domain)
+{
+ size_t ofs = error - OFPERR_OFS;
+
+ assert(ofperr_is_valid(error));
+ return &domain->errors[ofs];
+}
+
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;
return NULL;
}
- ofs = error - OFPERR_OFS;
- pair = &domain->errors[ofs];
+ pair = ofperr_get_pair__(error, domain);
if (!ofperr_is_nx_extension(error)) {
oem = make_openflow_xid(data_len + sizeof *oem, OFPT_ERROR, xid, &buf);
oem->type = htons(pair->type);
return ofperr_encode_msg__(error, domain, htonl(0), s, strlen(s));
}
+/* Returns the value that would go into an OFPT_ERROR message's 'type' for
+ * encoding 'error' in 'domain'. Returns -1 if 'error' is not encodable in
+ * 'domain'.
+ *
+ * 'error' must be a valid OFPERR_* code, as checked by ofperr_is_valid(). */
+int
+ofperr_get_type(enum ofperr error, const struct ofperr_domain *domain)
+{
+ return ofperr_get_pair__(error, domain)->type;
+}
+
+/* Returns the value that would go into an OFPT_ERROR message's 'code' for
+ * encoding 'error' in 'domain'. Returns -1 if 'error' is not encodable in
+ * 'domain' or if 'error' represents a category rather than a specific error.
+ *
+ * 'error' must be a valid OFPERR_* code, as checked by ofperr_is_valid(). */
+int
+ofperr_get_code(enum ofperr error, const struct ofperr_domain *domain)
+{
+ return ofperr_get_pair__(error, domain)->code;
+}
+
/* Tries to decodes 'oh', which should be an OpenFlow OFPT_ERROR message.
* Returns an OFPERR_* constant on success, 0 on failure.
*
#define OFPERR_OFS (1 << 30)
enum ofperr {
+/* Expected duplications. */
+
+ /* Expected: 3,5 in OF1.1 means both OFPBIC_BAD_EXPERIMENTER and
+ * OFPBIC_BAD_EXP_TYPE. */
+
/* ## ------------------ ## */
/* ## OFPET_HELLO_FAILED ## */
/* ## ------------------ ## */
/* OF1.1+(1,9). Specified table-id invalid or does not exist. */
OFPERR_OFPBRC_BAD_TABLE_ID,
+ /* OF1.2+(1,10). Denied because controller is slave. */
+ OFPERR_OFPBRC_IS_SLAVE,
+
+ /* OF1.2+(1,11). Invalid port. */
+ OFPERR_OFPBRC_BAD_PORT,
+
+ /* OF1.2+(1,12). Invalid packet in packet-out. */
+ OFPERR_OFPBRC_BAD_PACKET,
+
/* NX1.0+(1,256). Invalid NXM flow match. */
OFPERR_NXBRC_NXM_INVALID,
* nxm_hasmask or nxm_length or both, is invalid or not implemented. */
OFPERR_NXBRC_NXM_BAD_TYPE,
- /* NX1.0+(1,258). Invalid nxm_value. */
- OFPERR_NXBRC_NXM_BAD_VALUE,
-
- /* NX1.0+(1,259). Invalid nxm_mask. */
- OFPERR_NXBRC_NXM_BAD_MASK,
-
- /* NX1.0+(1,260). A prerequisite was not met. */
- OFPERR_NXBRC_NXM_BAD_PREREQ,
-
- /* NX1.0+(1,261). A given nxm_type was specified more than once. */
- OFPERR_NXBRC_NXM_DUP_TYPE,
-
/* NX1.0+(1,512). A request specified a nonexistent table ID. */
OFPERR_NXBRC_BAD_TABLE_ID,
- /* NX1.0+(1,513). NXT_ROLE_REQUEST specified an invalid role. */
- OFPERR_NXBRC_BAD_ROLE,
-
/* NX1.0+(1,514). The in_port in an ofp_packet_out request is invalid. */
OFPERR_NXBRC_BAD_IN_PORT,
/* OF1.1+(2,12). Actions uses an unsupported tag/encap. */
OFPERR_OFPBAC_BAD_TAG,
+ /* OF1.2+(2,13). Unsupported type in SET_FIELD action. */
+ OFPERR_OFPBAC_SET_TYPE,
+
+ /* OF1.2+(2,14). Length problem in SET_FIELD action. */
+ OFPERR_OFPBAC_SET_LEN,
+
+ /* OF1.2+(2,15). Bad argument in SET_FIELD action. */
+ OFPERR_OFPBAC_ARGUMENT,
+
/* NX1.0+(2,256). Must-be-zero action argument had nonzero value. */
OFPERR_NXBAC_MUST_BE_ZERO,
/* 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,
+ /* OF1.1+(3,5). Unknown experimenter id specified. */
+ OFPERR_OFPBIC_BAD_EXPERIMENTER,
+
+ /* OF1.1(3,5), OF1.2+(3,6). Unknown instruction for experimenter id. */
+ OFPERR_OFPBIC_BAD_EXP_TYPE,
+
+ /* OF1.2+(3,7). Length problem in instructions. */
+ OFPERR_OFPBIC_BAD_LEN,
+
+ /* OF1.2+(3,8). Permissions error. */
+ OFPERR_OFPBIC_EPERM,
/* ## --------------- ## */
/* ## OFPET_BAD_MATCH ## */
/* OF1.1+(4,6). Unsupported field in the match. */
OFPERR_OFPBMC_BAD_FIELD,
- /* OF1.1+(4,7). Unsupported value in a match field. */
+ /* NX1.0(1,258), NX1.1(1,258), OF1.2+(4,7). Unsupported value in a match
+ * field. */
OFPERR_OFPBMC_BAD_VALUE,
+ /* NX1.0(1,259), NX1.1(1,259), OF1.2+(4,8). Unsupported mask specified in
+ * the match, field is not dl-address or nw-address. */
+ OFPERR_OFPBMC_BAD_MASK,
+
+ /* NX1.0(1,260), NX1.1(1,260), OF1.2+(4,9). A prerequisite was not met. */
+ OFPERR_OFPBMC_BAD_PREREQ,
+
+ /* NX1.0(1,261), NX1.1(1,261), OF1.2+(4,10). A field type was
+ * duplicated. */
+ OFPERR_OFPBMC_DUP_FIELD,
+
+ /* OF1.2+(4,11). Permissions error. */
+ OFPERR_OFPBMC_EPERM,
+
/* ## --------------------- ## */
/* ## OFPET_FLOW_MOD_FAILED ## */
/* ## --------------------- ## */
/* OF1.0(3,4), OF1.1+(5,6). Unsupported or unknown command. */
OFPERR_OFPFMFC_BAD_COMMAND,
+ /* OF1.2+(5,7). Unsupported or unknown flags. */
+ OFPERR_OFPFMFC_BAD_FLAGS,
+
/* OF1.0(3,5). Unsupported action list - cannot process in the order
* specified. */
OFPERR_OFPFMFC_UNSUPPORTED,
* modify a non-existent group. */
OFPERR_OFPGMFC_UNKNOWN_GROUP,
+ /* OF1.2+(6,9). Group not deleted because another
+ group is forwarding to it. */
+ OFPERR_OFPGMFC_CHAINED_GROUP,
+
+ /* OF1.2+(6,10). Unsupported or unknown group type. */
+ OFPERR_OFPGMFC_BAD_TYPE,
+
+ /* OF1.2+(6,11). Unsupported or unknown command. */
+ OFPERR_OFPGMFC_BAD_COMMAND,
+
+ /* OF1.2+(6,12). Error in bucket. */
+ OFPERR_OFPGMFC_OFPGMFC_BAD_BUCKET,
+
+ /* OF1.2+(6,13). Error in watch port/group. */
+ OFPERR_OFPGMFC_OFPGMFC_BAD_WATCH,
+
+ /* OF1.2+(6,14). Permissions error. */
+ OFPERR_OFPGMFC_OFPGMFC_EPERM,
+
/* ## --------------------- ## */
/* ## OFPET_PORT_MOD_FAILED ## */
/* ## --------------------- ## */
/* OF1.1+(7,3). Specified advertise is invalid. */
OFPERR_OFPPMFC_BAD_ADVERTISE,
+ /* OF1.2+(7,4). Permissions error. */
+ OFPERR_OFPPMFC_EPERM,
+
/* ## ---------------------- ## */
/* ## OFPET_TABLE_MOD_FAILED ## */
/* ## ---------------------- ## */
/* OF1.1+(8,1). Specified config is invalid. */
OFPERR_OFPTMFC_BAD_CONFIG,
+ /* OF1.2+(8,2). Permissions error. */
+ OFPERR_OFPTMFC_EPERM,
+
/* ## --------------------- ## */
/* ## OFPET_QUEUE_OP_FAILED ## */
/* ## --------------------- ## */
/* OF1.1+(10,1). Specified len is invalid. */
OFPERR_OFPSCFC_BAD_LEN,
+
+ /* OF1.2+(10,2). Permissions error. */
+ OFPERR_OFPSCFC_EPERM,
+
+/* ## ------------------------- ## */
+/* ## OFPET_ROLE_REQUEST_FAILED ## */
+/* ## ------------------------- ## */
+
+ /* OF1.2+(11). Controller Role request failed. */
+ OFPERR_OFPET_ROLE_REQUEST_FAILED,
+
+ /* OF1.2+(11,0). Stale Message: old generation_id. */
+ OFPERR_OFPRRFC_STALE,
+
+ /* OF1.2+(11,1). Controller role change unsupported. */
+ OFPERR_OFPRRFC_UNSUP,
+
+ /* NX1.0(1,513), NX1.1(1,513), OF1.2+(11,2). Invalid role. */
+ OFPERR_OFPRRFC_BAD_ROLE,
+
+
+/* ## ------------------ ## */
+/* ## OFPET_EXPERIMENTER ## */
+/* ## ------------------ ## */
+
+ /* OF1.2+(0xffff). Experimenter error messages. */
+ OFPERR_OFPET_EXPERIMENTER,
};
extern const struct ofperr_domain ofperr_of10;
extern const struct ofperr_domain ofperr_of11;
+extern const struct ofperr_domain ofperr_of12;
const struct ofperr_domain *ofperr_domain_from_version(uint8_t version);
+const char *ofperr_domain_get_name(const struct ofperr_domain *);
bool ofperr_is_valid(enum ofperr);
bool ofperr_is_category(enum ofperr);
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_from_name(const char *);
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 *);
+int ofperr_get_type(enum ofperr, const struct ofperr_domain *);
+int ofperr_get_code(enum ofperr, const struct ofperr_domain *);
const char *ofperr_get_name(enum ofperr);
const char *ofperr_get_description(enum ofperr);
role = ntohl(nrr->role);
if (role != NX_ROLE_OTHER && role != NX_ROLE_MASTER
&& role != NX_ROLE_SLAVE) {
- return OFPERR_NXBRC_BAD_ROLE;
+ return OFPERR_OFPRRFC_BAD_ROLE;
}
if (ofconn_get_role(ofconn) != role
tests/daemon.at \
tests/daemon-py.at \
tests/ofp-print.at \
+ tests/ofp-errors.at \
tests/ovs-ofctl.at \
tests/odp.at \
tests/multipath.at \
--- /dev/null
+AT_BANNER([ofp-errors tests])
+
+AT_SETUP([OFPT_ERROR with type OFPET_HELLO_FAILED - OF1.0])
+AT_KEYWORDS([ofp-print ofp-errors])
+AT_CHECK([ovs-ofctl ofp-print 010100170000000000000001657874726120646174610a], [0], [dnl
+OFPT_ERROR (xid=0x0): OFPHFC_EPERM
+extra data\012
+])
+AT_CLEANUP
+
+AT_SETUP([OFPT_ERROR with type OFPET_HELLO_FAILED - OF1.1])
+AT_KEYWORDS([ofp-print ofp-errors])
+AT_CHECK([ovs-ofctl ofp-print 020100170000000000000001657874726120646174610a], [0], [dnl
+OFPT_ERROR (OF1.1) (xid=0x0): OFPHFC_EPERM
+extra data\012
+])
+AT_CLEANUP
+
+AT_SETUP([OFPT_ERROR with type OFPET_BAD_REQUEST - OF1.0])
+AT_KEYWORDS([ofp-print ofp-errors])
+AT_CHECK([ovs-ofctl ofp-print 01010014000000000001000601bbccddeeff0011], [0], [dnl
+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 OFPBMC_BAD_PREREQ - OF1.0])
+AT_KEYWORDS([ofp-print ofp-errors])
+AT_CHECK([ovs-ofctl ofp-print '0101001c55555555 b0c20000 0000232000010104 0102000811111111'], [0], [dnl
+OFPT_ERROR (xid=0x55555555): OFPBMC_BAD_PREREQ
+OFPT_ECHO_REQUEST (xid=0x11111111): 0 bytes of payload
+])
+AT_CLEANUP
+
+AT_SETUP([OFPT_ERROR with code OFPBMC_BAD_PREREQ - OF1.1])
+AT_KEYWORDS([ofp-print ofp-errors])
+AT_CHECK([ovs-ofctl ofp-print '0201001c55555555 b0c20000 0000232000010104 0102000811111111'], [0], [dnl
+OFPT_ERROR (OF1.1) (xid=0x55555555): OFPBMC_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 ofp-errors])
+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 ofp-errors])
+AT_CHECK([ovs-ofctl ofp-print 02010014000000000003000102bbccddeeff0011], [0], [dnl
+OFPT_ERROR (OF1.1) (xid=0x0): OFPBIC_UNSUP_INST
+(***truncated to 8 bytes from 52445***)
+00000000 02 bb cc dd ee ff 00 11- |........ |
+])
+AT_CLEANUP
+
+dnl OF1.1 had OFPBIC_UNSUP_EXP_INST as 3,5.
+dnl OF1.2 broke it into OFPBIC_BAD_EXPERIMENTER as 3,5
+dnl and OFPBIC_BAD_EXT_TYPE as 3,6.
+dnl Thus, for OF1.1 we translate both of the latter error codes into 3,5.
+AT_SETUP([encoding OFPBIC_* experimenter errors])
+AT_KEYWORDS([ofp-print ofp-errors])
+AT_CHECK([ovs-ofctl print-error OFPBIC_BAD_EXPERIMENTER], [0], [dnl
+OpenFlow 1.0: -1,-1
+OpenFlow 1.1: 3,5
+OpenFlow 1.2: 3,5
+])
+AT_CHECK([ovs-ofctl print-error OFPBIC_BAD_EXP_TYPE], [0], [dnl
+OpenFlow 1.0: -1,-1
+OpenFlow 1.1: 3,5
+OpenFlow 1.2: 3,6
+])
+AT_CLEANUP
+
+AT_SETUP([decoding OFPBIC_* experimenter errors])
+AT_KEYWORDS([ofp-print ofp-errors])
+AT_CHECK([ovs-ofctl ofp-print '0201001455555555 00030005 0102000811111111'], [0], [dnl
+OFPT_ERROR (OF1.1) (xid=0x55555555): OFPBIC_BAD_EXPERIMENTER
+OFPT_ECHO_REQUEST (xid=0x11111111): 0 bytes of payload
+])
+AT_KEYWORDS([ofp-print ofp-errors])
+AT_CHECK([ovs-ofctl ofp-print '0301001455555555 00030005 0102000811111111'], [0], [dnl
+OFPT_ERROR (OF 0x03) (xid=0x55555555): OFPBIC_BAD_EXPERIMENTER
+OFPT_ECHO_REQUEST (xid=0x11111111): 0 bytes of payload
+])
+AT_KEYWORDS([ofp-print ofp-errors])
+AT_CHECK([ovs-ofctl ofp-print '0301001455555555 00030006 0102000811111111'], [0], [dnl
+OFPT_ERROR (OF 0x03) (xid=0x55555555): OFPBIC_BAD_EXP_TYPE
+OFPT_ECHO_REQUEST (xid=0x11111111): 0 bytes of payload
+])
+AT_CLEANUP
])
AT_CLEANUP
-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): OFPHFC_EPERM
-extra data\012
-])
-AT_CLEANUP
-
-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 (OF1.1) (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): 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 - OF1.0])
-AT_KEYWORDS([ofp-print])
-AT_CHECK([ovs-ofctl ofp-print '0101001c55555555 b0c20000 0000232000010104 0102000811111111'], [0], [dnl
-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 (OF1.1) (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 (OF1.1) (xid=0x0): OFPBIC_UNSUP_INST
-(***truncated to 8 bytes from 52445***)
-00000000 02 bb cc dd ee ff 00 11- |........ |
-])
-AT_CLEANUP
+dnl OFPT_ERROR tests are in ofp-errors.at.
AT_SETUP([OFPT_ECHO_REQUEST, empty payload])
AT_KEYWORDS([ofp-print])
# vlan tci
NXM_OF_VLAN_TCI(f009)
-nx_pull_match() returned error NXBRC_NXM_DUP_TYPE
+nx_pull_match() returned error OFPBMC_DUP_FIELD
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 NXBRC_NXM_BAD_VALUE
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_VALUE
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# IP ECN
NXM_OF_ETH_TYPE(0800), NXM_NX_IP_ECN(03)
-nx_pull_match() returned error NXBRC_NXM_BAD_VALUE
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_VALUE
+nx_pull_match() returned error OFPBMC_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 NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_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 NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_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 NXBRC_NXM_BAD_PREREQ
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_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 NXBRC_NXM_BAD_PREREQ
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# TCP source port
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_SRC(4231)
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_SRC_W(5050/f0f0)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# TCP destination port
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_DST(4231)
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_DST_W(fde0/fff0)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# UDP source port
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_SRC(8732)
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_SRC_W(0132/01ff)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# UDP destination port
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_DST(1782)
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_DST_W(5005/f00f)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# ICMP type
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(01), NXM_OF_ICMP_TYPE(12)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# ICMP code
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(01), NXM_OF_ICMP_CODE(12)
-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
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# ARP opcode
NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_OP(0001)
-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
+nx_pull_match() returned error OFPBMC_BAD_VALUE
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_DUP_FIELD
# 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 NXBRC_NXM_BAD_PREREQ
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_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 NXBRC_NXM_BAD_PREREQ
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# ARP source hardware address
NXM_OF_ETH_TYPE(0806), NXM_NX_ARP_SHA(0002e30f80a4)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# ARP destination hardware address
NXM_OF_ETH_TYPE(0806), NXM_NX_ARP_THA(0002e30f80a4)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# IPv6 source
NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC(20010db83c4d00010002000300040005)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC_W(20010db83c4d00010000000000000000/ffffffffffffffff0000000000000000)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
# IPv6 destination
NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_DST(20010db83c4d00010002000300040005)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_DST_W(20010db83c4d00010000000000000000/ffffffffffffffff0000000000000000)
-nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_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 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 OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_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 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 OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_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 NXBRC_NXM_BAD_VALUE
+nx_pull_match() returned error OFPBMC_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 NXBRC_NXM_BAD_VALUE
+nx_pull_match() returned error OFPBMC_BAD_VALUE
# Flow cookie.
NXM_NX_COOKIE(00000000abcdef01)
NXM_NX_REG0_W(a0e0d050/f0f0f0f0)
# Invalid field number.
-nx_pull_match() returned error NXBRC_NXM_BAD_TYPE
+nx_pull_match() returned error OFPBMC_BAD_FIELD
# Unimplemented registers.
#
# registers are implemented.
NXM_NX_REG0(12345678)
NXM_NX_REG0_W(12345678/12345678)
-nx_pull_match() returned error NXBRC_NXM_BAD_TYPE
-nx_pull_match() returned error NXBRC_NXM_BAD_TYPE
+nx_pull_match() returned error OFPBMC_BAD_FIELD
+nx_pull_match() returned error OFPBMC_BAD_FIELD
])
AT_CLEANUP
])
AT_CHECK([ovs-ofctl --strict parse-nx-match < nx-match.txt], [0], [dnl
-nx_pull_match() returned error NXBRC_NXM_BAD_TYPE
+nx_pull_match() returned error OFPBMC_BAD_FIELD
])
AT_CHECK([ovs-ofctl parse-nx-match < nx-match.txt], [0], [dnl
m4_include([tests/daemon.at])
m4_include([tests/daemon-py.at])
m4_include([tests/ofp-print.at])
+m4_include([tests/ofp-errors.at])
m4_include([tests/ovs-ofctl.at])
m4_include([tests/odp.at])
m4_include([tests/multipath.at])
ds_destroy(&in);
}
+/* "print-error ENUM": Prints the type and code of ENUM for every OpenFlow
+ * version. */
+static void
+do_print_error(int argc OVS_UNUSED, char *argv[])
+{
+ enum ofperr error;
+ int version;
+
+ error = ofperr_from_name(argv[1]);
+ if (!error) {
+ ovs_fatal(0, "unknown error \"%s\"", argv[1]);
+ }
+
+ for (version = 0; version <= UINT8_MAX; version++) {
+ const struct ofperr_domain *domain;
+
+ domain = ofperr_domain_from_version(version);
+ if (!domain) {
+ continue;
+ }
+
+ printf("%s: %d,%d\n",
+ ofperr_domain_get_name(domain),
+ ofperr_get_type(error, domain),
+ ofperr_get_code(error, domain));
+ }
+}
+
/* "ofp-print HEXSTRING [VERBOSITY]": Converts the hex digits in HEXSTRING into
* binary data, interpreting them as an OpenFlow message, and prints the
* OpenFlow message on stdout, at VERBOSITY (level 2 by default). */
{ "parse-flow", 1, 1, do_parse_flow },
{ "parse-flows", 1, 1, do_parse_flows },
{ "parse-nx-match", 0, 0, do_parse_nx_match },
+ { "print-error", 1, 1, do_print_error },
{ "ofp-print", 1, 2, do_ofp_print },
{ NULL, 0, 0, NULL },