+/* Pretty-print the NXT_FLOW_EXPIRED packet of 'len' bytes at 'oh' to 'string'
+ * at the given 'verbosity' level. */
+static void
+nx_print_flow_end(struct ds *string, const void *oh, size_t len,
+ int verbosity)
+{
+ const struct nx_flow_end *nfe = oh;
+
+ ds_put_cstr(string, "nx_flow_end: ");
+
+ if (len < sizeof(*nfe)) {
+ ds_put_format(string, " (***length=%zu < min_size=%zu***)\n",
+ len, sizeof(*nfe));
+ return;
+ }
+
+ ofp_print_match(string, &nfe->match, verbosity);
+ ds_put_cstr(string, " reason=");
+ switch (nfe->reason) {
+ case NXFER_IDLE_TIMEOUT:
+ ds_put_cstr(string, "idle");
+ break;
+ case NXFER_HARD_TIMEOUT:
+ ds_put_cstr(string, "hard");
+ break;
+ case NXFER_DELETE:
+ ds_put_cstr(string, "delete");
+ break;
+ case NXFER_EJECT:
+ ds_put_cstr(string, "eject");
+ break;
+ default:
+ ds_put_format(string, "**%"PRIu8"**", nfe->reason);
+ break;
+ }
+ ds_put_format(string,
+ " pri=%"PRIu16" init=%"PRIu64" used=%"PRIu64" end=%"PRIu64,
+ nfe->match.wildcards ? ntohs(nfe->priority) : (uint16_t)-1,
+ ntohll(nfe->init_time), ntohll(nfe->used_time),
+ ntohll(nfe->end_time));
+ ds_put_format(string,
+ " tflags=0x%x tos=0x%x pkts=%"PRIu64" bytes=%"PRIu64"\n",
+ nfe->tcp_flags, nfe->ip_tos, ntohll(nfe->packet_count),
+ ntohll(nfe->byte_count));
+}
+
+static void
+nx_print_msg(struct ds *string, const void *oh, size_t len, int verbosity)
+{
+ const struct nicira_header *nh = oh;
+
+ switch(ntohl(nh->subtype))
+ {
+ case NXT_FLOW_END:
+ nx_print_flow_end(string, oh, len, verbosity);
+ return;
+ }
+}
+
+
+static void
+ofp_print_port_mod(struct ds *string, const void *oh, size_t len,
+ int verbosity)
+{
+ const struct ofp_port_mod *opm = oh;
+
+ ds_put_format(string, "port: %d: addr:"ETH_ADDR_FMT", config: %#x, mask:%#x\n",
+ ntohs(opm->port_no), ETH_ADDR_ARGS(opm->hw_addr),
+ ntohl(opm->config), ntohl(opm->mask));
+ ds_put_format(string, " advertise: ");
+ if (opm->advertise) {
+ ofp_print_port_features(string, ntohl(opm->advertise));
+ } else {
+ ds_put_format(string, "UNCHANGED\n");
+ }
+}
+
+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_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_VERSION),
+
+ 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_TYPE(OFPET_FLOW_MOD_FAILED),
+ ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL)
+};
+#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 "?";
+}