summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2011-01-12 13:42:50 -0800
committerBen Pfaff <blp@nicira.com>2011-01-12 13:51:43 -0800
commitdc4762edd02693770d392b8f6495deb7e52635bf (patch)
tree92ed4ec143b5d99170a479ab4d95f9cb627eb389 /lib
parenta44d74d75294e358e501cc83fd35e6a5e50ebf0b (diff)
downloadopenvswitch-dc4762edd02693770d392b8f6495deb7e52635bf.tar.gz
Automatically extract error types and codes for formatting.
Diffstat (limited to 'lib')
-rw-r--r--lib/.gitignore1
-rw-r--r--lib/automake.mk10
-rw-r--r--lib/ofp-errors.h28
-rw-r--r--lib/ofp-print.c149
-rw-r--r--lib/ofp-util.c115
-rw-r--r--lib/ofp-util.h7
6 files changed, 181 insertions, 129 deletions
diff --git a/lib/.gitignore b/lib/.gitignore
index d56deecbe..c5b6cac94 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -3,3 +3,4 @@
/dhparams.c
/dirs.c
/coverage-counters.c
+/ofp-errors.c
diff --git a/lib/automake.mk b/lib/automake.mk
index f5d23a23b..269ab897f 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -81,6 +81,8 @@ lib_libopenvswitch_a_SOURCES = \
lib/nx-match.h \
lib/odp-util.c \
lib/odp-util.h \
+ lib/ofp-errors.c \
+ lib/ofp-errors.h \
lib/ofp-parse.c \
lib/ofp-parse.h \
lib/ofp-print.c \
@@ -245,6 +247,14 @@ lib/dirs.c: lib/dirs.c.in Makefile
> lib/dirs.c.tmp
mv lib/dirs.c.tmp lib/dirs.c
+$(srcdir)/lib/ofp-errors.c: \
+ include/openflow/openflow.h include/openflow/nicira-ext.h \
+ build-aux/extract-ofp-errors
+ cd $(srcdir)/include && \
+ $(PYTHON) ../build-aux/extract-ofp-errors \
+ openflow/openflow.h openflow/nicira-ext.h > ../lib/ofp-errors.c
+EXTRA_DIST += build-aux/extract-ofp-errors
+
install-data-local: lib-install-data-local
lib-install-data-local:
$(MKDIR_P) $(DESTDIR)$(RUNDIR)
diff --git a/lib/ofp-errors.h b/lib/ofp-errors.h
new file mode 100644
index 000000000..d677b5d45
--- /dev/null
+++ b/lib/ofp-errors.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2008, 2009, 2010 Nicira Networks.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OFP_ERRORS_H
+#define OFP_ERRORS_H 1
+
+#include <stdint.h>
+
+/* These functions are building blocks for the ofputil_format_error() and
+ * ofputil_error_to_string() functions declared in ofp-util.h. Those functions
+ * have friendlier interfaces and should usually be preferred. */
+const char *ofp_error_type_to_string(uint16_t value);
+const char *ofp_error_code_to_string(uint16_t type, uint16_t code);
+
+#endif /* ofp-errors.h */
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index d88a574cb..9d1b3b0c0 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -953,158 +953,52 @@ ofp_print_port_mod(struct ds *string, const struct ofp_port_mod *opm)
}
}
-struct error_type {
- int type;
- int code;
- const char *name;
-};
-
-static const struct error_type error_types[] = {
-#define ERROR_TYPE(TYPE) {TYPE, -1, #TYPE}
-#define ERROR_CODE(TYPE, CODE) {TYPE, CODE, #CODE}
- ERROR_TYPE(OFPET_HELLO_FAILED),
- ERROR_CODE(OFPET_HELLO_FAILED, OFPHFC_INCOMPATIBLE),
- ERROR_CODE(OFPET_HELLO_FAILED, OFPHFC_EPERM),
-
- ERROR_TYPE(OFPET_BAD_REQUEST),
- ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION),
- ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE),
- ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_STAT),
- ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR),
- ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE),
- ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_EPERM),
- ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN),
- ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BUFFER_EMPTY),
- ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BUFFER_UNKNOWN),
- /* Nicira error extensions. */
- ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_INVALID),
- ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_TYPE),
- ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_VALUE),
- ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_MASK),
- ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_PREREQ),
- ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_DUP_TYPE),
-
- ERROR_TYPE(OFPET_BAD_ACTION),
- ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_TYPE),
- ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_LEN),
- ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR),
- ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR_TYPE),
- ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT),
- ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT),
- ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_EPERM),
- ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_TOO_MANY),
-
- ERROR_TYPE(OFPET_FLOW_MOD_FAILED),
- ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL),
- ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP),
- ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_EPERM),
- ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_EMERG_TIMEOUT),
- ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_COMMAND),
- /* Nicira error extenstions. */
- ERROR_CODE(OFPET_FLOW_MOD_FAILED, NXFMFC_HARDWARE),
- ERROR_CODE(OFPET_FLOW_MOD_FAILED, NXFMFC_BAD_TABLE_ID),
-
- ERROR_TYPE(OFPET_PORT_MOD_FAILED),
- ERROR_CODE(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_PORT),
- ERROR_CODE(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_HW_ADDR)
-};
-#define N_ERROR_TYPES ARRAY_SIZE(error_types)
-
-static const char *
-lookup_error_type(int type)
-{
- const struct error_type *t;
-
- for (t = error_types; t < &error_types[N_ERROR_TYPES]; t++) {
- if (t->type == type && t->code == -1) {
- return t->name;
- }
- }
- return "?";
-}
-
-static const char *
-lookup_error_code(int type, int code)
-{
- const struct error_type *t;
-
- for (t = error_types; t < &error_types[N_ERROR_TYPES]; t++) {
- if (t->type == type && t->code == code) {
- return t->name;
- }
- }
- return "?";
-}
-
static void
ofp_print_error(struct ds *string, int error)
{
- int type = get_ofp_err_type(error);
- int code = get_ofp_err_code(error);
if (string->length) {
ds_put_char(string, ' ');
}
- ds_put_format(string, " ***decode error type:%d(%s) code:%d(%s)***\n",
- type, lookup_error_type(type),
- code, lookup_error_code(type, code));
-}
-
-static void
-ofp_print_nx_error_msg(struct ds *string, const struct ofp_error_msg *oem)
-{
- size_t len = ntohs(oem->header.length);
- const struct nx_vendor_error *nve = (struct nx_vendor_error *)oem->data;
- int vendor = ntohl(nve->vendor);
- int type = ntohs(nve->type);
- int code = ntohs(nve->code);
-
- ds_put_format(string, " vendor:%x type:%d(%s) code:%d(%s) payload:\n",
- vendor,
- type, lookup_error_type(type),
- code, lookup_error_code(type, code));
-
- ds_put_hex_dump(string, nve + 1, len - sizeof *oem - sizeof *nve,
- 0, true);
+ ds_put_cstr(string, "***decode error: ");
+ ofputil_format_error(string, error);
+ ds_put_cstr(string, "***\n");
}
static void
ofp_print_error_msg(struct ds *string, const struct ofp_error_msg *oem)
{
size_t len = ntohs(oem->header.length);
- int type = ntohs(oem->type);
- int code = ntohs(oem->code);
+ size_t payload_ofs, payload_len;
+ const void *payload;
+ int error;
char *s;
-
- if (type == NXET_VENDOR && code == NXVC_VENDOR_ERROR) {
- if (len < sizeof *oem + sizeof(struct nx_vendor_error)) {
- ds_put_format(string,
- "(***truncated extended error message is %zu bytes "
- "when it should be at least %zu***)\n",
- len, sizeof(struct nx_vendor_error));
- return;
- }
-
- return ofp_print_nx_error_msg(string, oem);
+ error = ofputil_decode_error_msg(&oem->header, &payload_ofs);
+ if (!is_ofp_error(error)) {
+ ofp_print_error(string, error);
+ ds_put_hex_dump(string, oem->data, len - sizeof *oem, 0, true);
+ return;
}
- ds_put_format(string, " type:%d(%s) code:%d(%s) payload:\n",
- type, lookup_error_type(type),
- code, lookup_error_code(type, code));
+ ds_put_char(string, ' ');
+ ofputil_format_error(string, error);
+ ds_put_char(string, '\n');
- switch (type) {
+ payload = (const uint8_t *) oem + payload_ofs;
+ payload_len = len - payload_ofs;
+ switch (get_ofp_err_type(error)) {
case OFPET_HELLO_FAILED:
- ds_put_printable(string, (char *) oem->data, len - sizeof *oem);
+ ds_put_printable(string, payload, payload_len);
break;
case OFPET_BAD_REQUEST:
- s = ofp_to_string(oem->data, len - sizeof *oem, 1);
+ s = ofp_to_string(payload, payload_len, 1);
ds_put_cstr(string, s);
free(s);
break;
default:
- ds_put_hex_dump(string, oem->data, len - sizeof *oem, 0, true);
+ ds_put_hex_dump(string, payload, payload_len, 0, true);
break;
}
}
@@ -1569,6 +1463,9 @@ ofp_to_string__(const struct ofp_header *oh,
break;
case OFPUTIL_OFPT_HELLO:
+ ds_put_char(string, '\n');
+ ds_put_hex_dump(string, oh + 1, ntohs(oh->length) - sizeof *oh,
+ 0, true);
break;
case OFPUTIL_OFPT_ERROR:
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 9210413a1..7aea3319e 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,12 +16,15 @@
#include <config.h>
#include "ofp-print.h"
+#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include "byte-order.h"
#include "classifier.h"
+#include "dynamic-string.h"
#include "multipath.h"
#include "nx-match.h"
+#include "ofp-errors.h"
#include "ofp-util.h"
#include "ofpbuf.h"
#include "packets.h"
@@ -2043,6 +2046,18 @@ vendor_code_to_id(uint8_t code)
}
}
+static int
+vendor_id_to_code(uint32_t id)
+{
+ switch (id) {
+#define OFPUTIL_VENDOR(NAME, VENDOR_ID) case VENDOR_ID: return NAME;
+ OFPUTIL_VENDORS
+#undef OFPUTIL_VENDOR
+ default:
+ return -1;
+ }
+}
+
/* Creates and returns an OpenFlow message of type OFPT_ERROR with the error
* information taken from 'error', whose encoding must be as described in the
* large comment in ofp-util.h. If 'oh' is nonnull, then the error will use
@@ -2051,7 +2066,7 @@ vendor_code_to_id(uint8_t code)
*
* Returns NULL if 'error' is not an OpenFlow error code. */
struct ofpbuf *
-make_ofp_error_msg(int error, const struct ofp_header *oh)
+ofputil_encode_error_msg(int error, const struct ofp_header *oh)
{
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
@@ -2124,6 +2139,102 @@ make_ofp_error_msg(int error, const struct ofp_header *oh)
return buf;
}
+/* Decodes 'oh', which should be an OpenFlow OFPT_ERROR message, and returns an
+ * Open vSwitch internal error code in the format described in the large
+ * comment in ofp-util.h.
+ *
+ * If 'payload_ofs' is nonnull, on success '*payload_ofs' is set to the offset
+ * to the payload starting from 'oh' and on failure it is set to 0. */
+int
+ofputil_decode_error_msg(const struct ofp_header *oh, size_t *payload_ofs)
+{
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+
+ const struct ofp_error_msg *oem;
+ uint16_t type, code;
+ struct ofpbuf b;
+ int vendor;
+
+ if (payload_ofs) {
+ *payload_ofs = 0;
+ }
+ if (oh->type != OFPT_ERROR) {
+ return EPROTO;
+ }
+
+ ofpbuf_use_const(&b, oh, ntohs(oh->length));
+ oem = ofpbuf_try_pull(&b, sizeof *oem);
+ if (!oem) {
+ return EPROTO;
+ }
+
+ type = ntohs(oem->type);
+ code = ntohs(oem->code);
+ if (type == NXET_VENDOR && code == NXVC_VENDOR_ERROR) {
+ const struct nx_vendor_error *nve = ofpbuf_try_pull(&b, sizeof *nve);
+ if (!nve) {
+ return EPROTO;
+ }
+
+ vendor = vendor_id_to_code(ntohl(nve->vendor));
+ if (vendor < 0) {
+ VLOG_WARN_RL(&rl, "error contains unknown vendor ID %#"PRIx32,
+ ntohl(nve->vendor));
+ return EPROTO;
+ }
+ type = ntohs(nve->type);
+ code = ntohs(nve->code);
+ } else {
+ vendor = OFPUTIL_VENDOR_OPENFLOW;
+ }
+
+ if (type >= 1024) {
+ VLOG_WARN_RL(&rl, "error contains type %"PRIu16" greater than "
+ "supported maximum value 1023", type);
+ return EPROTO;
+ }
+
+ if (payload_ofs) {
+ *payload_ofs = (uint8_t *) b.data - (uint8_t *) oh;
+ }
+ return ofp_mkerr_vendor(vendor, type, code);
+}
+
+void
+ofputil_format_error(struct ds *s, int error)
+{
+ if (is_errno(error)) {
+ ds_put_cstr(s, strerror(error));
+ } else {
+ uint16_t type = get_ofp_err_type(error);
+ uint16_t code = get_ofp_err_code(error);
+ const char *type_s = ofp_error_type_to_string(type);
+ const char *code_s = ofp_error_code_to_string(type, code);
+
+ ds_put_format(s, "type ");
+ if (type_s) {
+ ds_put_cstr(s, type_s);
+ } else {
+ ds_put_format(s, "%"PRIu16, type);
+ }
+
+ ds_put_cstr(s, ", code ");
+ if (code_s) {
+ ds_put_cstr(s, code_s);
+ } else {
+ ds_put_format(s, "%"PRIu16, code);
+ }
+ }
+}
+
+char *
+ofputil_error_to_string(int error)
+{
+ struct ds s = DS_EMPTY_INITIALIZER;
+ ofputil_format_error(&s, error);
+ return ds_steal_cstr(&s);
+}
+
/* Attempts to pull 'actions_len' bytes from the front of 'b'. Returns 0 if
* successful, otherwise an OpenFlow error.
*
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 42318654b..5d9e8c4d0 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -384,6 +384,11 @@ get_ofp_err_code(int error)
return error & 0xffff;
}
-struct ofpbuf *make_ofp_error_msg(int error, const struct ofp_header *);
+struct ofpbuf *ofputil_encode_error_msg(int error, const struct ofp_header *);
+int ofputil_decode_error_msg(const struct ofp_header *, size_t *payload_ofs);
+
+/* String versions of errors. */
+void ofputil_format_error(struct ds *, int error);
+char *ofputil_error_to_string(int error);
#endif /* ofp-util.h */