Add error codes for Open Flow v1.2
authorSimon Horman <horms@verge.net.au>
Mon, 26 Mar 2012 20:46:35 +0000 (13:46 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 27 Mar 2012 16:17:40 +0000 (09:17 -0700)
* 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 <horms@verge.net.au>
[blp@nicira.com added better error checking in extract-ofp-errors, added
 unit tests, miscellaneous cleanup]
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Simon Horman <horms@verge.net.au>
build-aux/extract-ofp-errors
lib/nx-match.c
lib/ofp-errors.c
lib/ofp-errors.h
ofproto/ofproto.c
tests/automake.mk
tests/ofp-errors.at [new file with mode: 0644]
tests/ofp-print.at
tests/ovs-ofctl.at
tests/testsuite.at
utilities/ovs-ofctl.c

index 4b3d46ba2e3b9d9501238438a806c93b30ffbca5..efaf103bca79cc6dc8b98805d8ef4c76e4f806be 100755 (executable)
@@ -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 = 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 """\
@@ -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:
index 3ead9b614da050308d85a9cd56a523b3a76f33ee..0e61d35254de2b66c419d2444fb48bf509c454b3 100644 (file)
@@ -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
index 028475e114ba14c2f0b7c930ee16b78b4d2c62c7..e1349b094e05269efc0c1b1ff5225d5d94712e9d 100644 (file)
@@ -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.
  *
index bd6095b394a3d6a2193aa486014c27936684e1f4..40e5a61ab22c84bf31c239be5a27b381f6756a3b 100644 (file)
@@ -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);
index aa97124f49f99e85fc300d0aa70b07742bdc196a..e7e040126eb12c13259b78e2d13e66e7f43673be 100644 (file)
@@ -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
index 77281579fa3f59a5c41fd6f6a71d7a60b4aea54d..62f0c496bb72d5aaeaff7a5d8c350f6741f6ac9a 100644 (file)
@@ -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 (file)
index 0000000..5f76294
--- /dev/null
@@ -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
index 9ac1d23f96fb496c8d2e266c1b00f684e4d6f020..31d329356a5c2361fd181352dfdb8d39b603d330 100644 (file)
@@ -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])
index 039592570cfc0a3d6c3d9287714368f2078f175e..a52382eaa2bb809e5cb63160fd39563a65a5bb8d 100644 (file)
@@ -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
index 755462cb8981d3b7cb07830c5b3d6295a953b086..60401d6937c37c5d34a678028fbc15610b949c73 100644 (file)
@@ -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])
index 74a86c182a742edd1f106d280753148c4cfaf93a..3e9f4628e7140dd6200e0f53ef15077453ebe3b6 100644 (file)
@@ -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 },