On Mon, Mar 26, 2012 at 01:59:20PM -0700, Ben Pfaff wrote: > From: Simon Horman <ho...@verge.net.au> > > * Where Open Flow 1.2 breaks apart error codes defined > in previous versions, provide all new definitions to > previous versions and map the numeric error code to > the first first definition supplied in ofp-errors.h. > The case handled so far is: > OFPERR_OFPBIC_BAD_EXP_TYPE -> { OFPERR_OFPBIC_BAD_EXPERIMENTER, > OFPERR_OFPBIC_BAD_EXP_TYPE } > > * Where Open Flow 1.2 adds error codes that were previously > defined as Nicira extension errors define the later in terms > of the new codes. > > Signed-off-by: Simon Horman <ho...@verge.net.au> > [b...@nicira.com added better error checking in extract-ofp-errors, added > unit tests, miscellaneous cleanup] > Signed-off-by: Ben Pfaff <b...@nicira.com>
Hi Ben, this looks much more robust than my attempt. Ack. > --- > build-aux/extract-ofp-errors | 92 ++++++++++++++++++++++++------ > lib/nx-match.c | 16 +++--- > lib/ofp-errors.c | 61 +++++++++++++++++++- > lib/ofp-errors.h | 128 > ++++++++++++++++++++++++++++++++++++------ > ofproto/ofproto.c | 2 +- > tests/automake.mk | 1 + > tests/ofp-errors.at | 97 +++++++++++++++++++++++++++++++ > tests/ofp-print.at | 60 +------------------- > tests/ovs-ofctl.at | 94 +++++++++++++++--------------- > tests/testsuite.at | 1 + > utilities/ovs-ofctl.c | 29 ++++++++++ > 11 files changed, 427 insertions(+), 154 deletions(-) > create mode 100644 tests/ofp-errors.at > > diff --git a/build-aux/extract-ofp-errors b/build-aux/extract-ofp-errors > index 4b3d46b..7054408 100755 > --- a/build-aux/extract-ofp-errors > +++ b/build-aux/extract-ofp-errors > @@ -66,8 +66,14 @@ def getToken(): > 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(): > @@ -145,10 +151,13 @@ def extract_ofp_errors(filenames): > 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 > @@ -168,13 +177,10 @@ def extract_ofp_errors(filenames): > 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(): > @@ -182,6 +188,17 @@ def extract_ofp_errors(filenames): > 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) > @@ -194,35 +211,68 @@ def extract_ofp_errors(filenames): > 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 -*- */ > > @@ -254,12 +304,17 @@ static enum ofperr > %s_decode(uint16_t type, uint16_t code) > { > switch ((type << 16) | code) {""" % name > + found = [] > 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.append(value) > print " case (%d << 16) | %d:" % (type_, code) > print " return OFPERR_%s;" % enum > print """\ > @@ -307,6 +362,7 @@ const struct ofperr_domain %s = { > > 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: > diff --git a/lib/nx-match.c b/lib/nx-match.c > index 3ead9b6..0e61d35 100644 > --- a/lib/nx-match.c > +++ b/lib/nx-match.c > @@ -103,7 +103,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, > bool strict, > VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a " > "multiple of 8, is longer than space in message (max " > "length %zu)", match_len, b->size); > - return OFPERR_OFPBRC_BAD_LEN; > + return OFPERR_OFPBMC_BAD_LEN; > } > > cls_rule_init_catchall(rule, priority); > @@ -119,21 +119,21 @@ nx_pull_match__(struct ofpbuf *b, unsigned int > match_len, bool strict, > 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); > @@ -142,7 +142,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, > bool strict, > > memcpy(&mask, p + 4 + width, width); > if (!mf_is_mask_valid(mf, &mask)) { > - error = OFPERR_NXBRC_NXM_BAD_MASK; > + error = OFPERR_OFPBMC_BAD_MASK; > } else { > error = 0; > mf_set(mf, &value, &mask, rule); > @@ -153,7 +153,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, > bool strict, > /* Check if the match is for a cookie rather than a classifier rule. > */ > if ((header == NXM_NX_COOKIE || header == NXM_NX_COOKIE_W) && > cookie) { > if (*cookie_mask) { > - error = OFPERR_NXBRC_NXM_DUP_TYPE; > + error = OFPERR_OFPBMC_DUP_FIELD; > } else { > unsigned int width = sizeof *cookie; > > @@ -178,7 +178,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, > bool strict, > } > } > > - 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 > diff --git a/lib/ofp-errors.c b/lib/ofp-errors.c > index 028475e..e1349b0 100644 > --- a/lib/ofp-errors.c > +++ b/lib/ofp-errors.c > @@ -25,9 +25,17 @@ ofperr_domain_from_version(uint8_t version) > { > 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) > @@ -97,6 +105,24 @@ ofperr_get_name(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. */ > @@ -108,6 +134,15 @@ ofperr_get_description(enum ofperr error) > : "<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) > @@ -115,7 +150,6 @@ ofperr_encode_msg__(enum ofperr error, const struct > ofperr_domain *domain, > struct ofp_error_msg *oem; > const struct pair *pair; > struct ofpbuf *buf; > - size_t ofs; > > if (!domain) { > return NULL; > @@ -140,8 +174,7 @@ ofperr_encode_msg__(enum ofperr error, const struct > ofperr_domain *domain, > 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); > @@ -210,6 +243,28 @@ ofperr_encode_hello(enum ofperr error, const struct > ofperr_domain *domain, > 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. > * > diff --git a/lib/ofp-errors.h b/lib/ofp-errors.h > index bd6095b..40e5a61 100644 > --- a/lib/ofp-errors.h > +++ b/lib/ofp-errors.h > @@ -44,6 +44,11 @@ struct ofp_header; > #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 ## */ > /* ## ------------------ ## */ > @@ -95,6 +100,15 @@ enum ofperr { > /* 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, > > @@ -102,24 +116,9 @@ enum ofperr { > * 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, > > @@ -177,6 +176,15 @@ enum ofperr { > /* 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, > > @@ -202,8 +210,17 @@ enum ofperr { > /* 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 ## */ > @@ -235,9 +252,24 @@ enum ofperr { > /* 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 ## */ > /* ## --------------------- ## */ > @@ -274,6 +306,9 @@ enum ofperr { > /* 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, > @@ -325,6 +360,25 @@ enum ofperr { > * 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 ## */ > /* ## --------------------- ## */ > @@ -345,6 +399,9 @@ enum ofperr { > /* 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 ## */ > /* ## ---------------------- ## */ > @@ -358,6 +415,9 @@ enum ofperr { > /* 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 ## */ > /* ## --------------------- ## */ > @@ -386,12 +446,41 @@ enum ofperr { > > /* 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); > @@ -401,11 +490,14 @@ 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_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); > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c > index aa97124..e7e0401 100644 > --- a/ofproto/ofproto.c > +++ b/ofproto/ofproto.c > @@ -3064,7 +3064,7 @@ handle_role_request(struct ofconn *ofconn, const struct > ofp_header *oh) > 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 > diff --git a/tests/automake.mk b/tests/automake.mk > index 7728157..62f0c49 100644 > --- a/tests/automake.mk > +++ b/tests/automake.mk > @@ -15,6 +15,7 @@ TESTSUITE_AT = \ > 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 \ > diff --git a/tests/ofp-errors.at b/tests/ofp-errors.at > new file mode 100644 > index 0000000..5f76294 > --- /dev/null > +++ b/tests/ofp-errors.at > @@ -0,0 +1,97 @@ > +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 > diff --git a/tests/ofp-print.at b/tests/ofp-print.at > index 9ac1d23..31d3293 100644 > --- a/tests/ofp-print.at > +++ b/tests/ofp-print.at > @@ -57,65 +57,7 @@ OFPT_HELLO (xid=0x0): > ]) > 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]) > diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at > index 0395925..a52382e 100644 > --- a/tests/ovs-ofctl.at > +++ b/tests/ovs-ofctl.at > @@ -433,7 +433,7 @@ NXM_OF_IN_PORT(0012), NXM_OF_ETH_TYPE(0800) > > # 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) > @@ -443,118 +443,118 @@ NXM_OF_VLAN_TCI_W(0000/e000) > > # 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) > @@ -567,7 +567,7 @@ NXM_OF_ETH_TYPE(0800), NXM_NX_IP_FRAG_W(00/02) > NXM_OF_ETH_TYPE(0800), NXM_NX_IP_FRAG_W(01/01) > NXM_OF_ETH_TYPE(0800), NXM_NX_IP_FRAG_W(02/02) > NXM_OF_ETH_TYPE(0800), NXM_NX_IP_FRAG(03) > -nx_pull_match() returned error NXBRC_NXM_BAD_VALUE > +nx_pull_match() returned error OFPBMC_BAD_VALUE > > # IPv6 fragments. > NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_FRAG(00) > @@ -580,7 +580,7 @@ NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_FRAG_W(00/02) > NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_FRAG_W(01/01) > NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_FRAG_W(02/02) > NXM_OF_ETH_TYPE(86dd), NXM_NX_IP_FRAG(03) > -nx_pull_match() returned error NXBRC_NXM_BAD_VALUE > +nx_pull_match() returned error OFPBMC_BAD_VALUE > > # Flow cookie. > NXM_NX_COOKIE(00000000abcdef01) > @@ -595,7 +595,7 @@ NXM_NX_REG0(acebdf56) > 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. > # > @@ -603,8 +603,8 @@ nx_pull_match() returned error NXBRC_NXM_BAD_TYPE > # 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 > > @@ -615,7 +615,7 @@ NXM_OF_IN_PORT(0001), 01020304(1111/2222), > NXM_OF_ETH_TYPE(0800) > ]) > > AT_CHECK([ovs-ofctl --strict parse-nx-match < nx-match.txt], [0], [dnl > -nx_pull_match() returned error NXBRC_NXM_BAD_TYPE > +nx_pull_match() returned error OFPBMC_BAD_FIELD > ]) > > AT_CHECK([ovs-ofctl parse-nx-match < nx-match.txt], [0], [dnl > diff --git a/tests/testsuite.at b/tests/testsuite.at > index 755462c..60401d6 100644 > --- a/tests/testsuite.at > +++ b/tests/testsuite.at > @@ -57,6 +57,7 @@ m4_include([tests/check-structs.at]) > 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]) > diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c > index 74a86c1..3e9f462 100644 > --- a/utilities/ovs-ofctl.c > +++ b/utilities/ovs-ofctl.c > @@ -1832,6 +1832,34 @@ do_parse_nx_match(int argc OVS_UNUSED, char *argv[] > OVS_UNUSED) > 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). */ > @@ -1877,6 +1905,7 @@ static const struct command all_commands[] = { > { "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 }, > -- > 1.7.2.5 > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev