#include "compiler.h"
#include "dynamic-string.h"
#include "flow.h"
+#include "multipath.h"
#include "nx-match.h"
#include "ofp-util.h"
#include "ofpbuf.h"
case NXAST_REG_LOAD: return sizeof(struct nx_action_reg_load);
case NXAST_NOTE: return -1;
case NXAST_SET_TUNNEL64: return sizeof(struct nx_action_set_tunnel64);
+ case NXAST_MULTIPATH: return sizeof(struct nx_action_multipath);
default: return -1;
}
}
const struct nx_action_resubmit *nar;
const struct nx_action_reg_move *move;
const struct nx_action_reg_load *load;
+ const struct nx_action_multipath *nam;
switch ((enum nx_action_subtype) subtype) {
case NXAST_RESUBMIT:
return;
case NXAST_SET_TUNNEL64:
- nast64 = (struct nx_action_set_tunnel64 *) nah;
+ nast64 = (const struct nx_action_set_tunnel64 *) nah;
ds_put_format(string, "set_tunnel64:%#"PRIx64,
ntohll(nast64->tun_id));
return;
+ case NXAST_MULTIPATH:
+ nam = (const struct nx_action_multipath *) nah;
+ multipath_format(nam, string);
+ return;
+
case NXAST_SNAT__OBSOLETE:
default:
break;
enum ofputil_msg_code code, int verbosity)
{
struct flow_mod fm;
+ bool need_priority;
int error;
error = ofputil_decode_flow_mod(&fm, oh, NXFF_OPENFLOW10);
ds_put_char(s, ' ');
if (verbosity >= 3 && code == OFPUTIL_OFPT_FLOW_MOD) {
const struct ofp_flow_mod *ofm = (const struct ofp_flow_mod *) oh;
-
ofp_print_match(s, &ofm->match, verbosity);
+
+ /* ofp_print_match() doesn't print priority. */
+ need_priority = true;
} else if (verbosity >= 3 && code == OFPUTIL_NXT_FLOW_MOD) {
const struct nx_flow_mod *nfm = (const struct nx_flow_mod *) oh;
const void *nxm = nfm + 1;
- char *nxm_s = nx_match_to_string(nxm, ntohs(nfm->match_len));
+ char *nxm_s;
+
+ nxm_s = nx_match_to_string(nxm, ntohs(nfm->match_len));
ds_put_cstr(s, nxm_s);
free(nxm_s);
+
+ /* nx_match_to_string() doesn't print priority. */
+ need_priority = true;
} else {
cls_rule_format(&fm.cr, s);
+
+ /* cls_rule_format() does print priority. */
+ need_priority = false;
}
if (ds_last(s) != ' ') {
if (fm.hard_timeout != OFP_FLOW_PERMANENT) {
ds_put_format(s, "hard:%"PRIu16" ", fm.hard_timeout);
}
- if (fm.cr.priority != OFP_DEFAULT_PRIORITY && verbosity >= 3) {
+ if (fm.cr.priority != OFP_DEFAULT_PRIORITY && need_priority) {
ds_put_format(s, "pri:%"PRIu16" ", fm.cr.priority);
}
if (fm.buffer_id != UINT32_MAX) {
if (string->length) {
ds_put_char(string, ' ');
}
- ds_put_format(string, " ***decode error type:%d(%s) code:%d(%s)***",
+ ds_put_format(string, " ***decode error type:%d(%s) code:%d(%s)***\n",
type, lookup_error_type(type),
code, lookup_error_code(type, code));
}
ofp_print_duration(string, ntohl(fs->duration_sec),
ntohl(fs->duration_nsec));
ds_put_format(string, ", table_id=%"PRIu8", ", fs->table_id);
- ds_put_format(string, "priority=%"PRIu16", ", ntohs(fs->priority));
ds_put_format(string, "n_packets=%"PRIu64", ",
ntohll(fs->packet_count));
ds_put_format(string, "n_bytes=%"PRIu64", ", ntohll(fs->byte_count));
struct ds string = DS_EMPTY_INITIALIZER;
const struct ofp_header *oh = oh_;
- if (len < sizeof(struct ofp_header)) {
- ds_put_cstr(&string, "OpenFlow packet too short:\n");
+ if (!len) {
+ ds_put_cstr(&string, "OpenFlow message is empty\n");
+ } else if (len < sizeof(struct ofp_header)) {
+ ds_put_format(&string, "OpenFlow packet too short (only %zu bytes):\n",
+ len);
} else if (oh->version != OFP_VERSION) {
ds_put_format(&string, "Bad OpenFlow version %"PRIu8":\n",
oh->version);
} else if (ntohs(oh->length) > len) {
ds_put_format(&string,
- "(***truncated to %zu bytes from %"PRIu16"***)",
+ "(***truncated to %zu bytes from %"PRIu16"***)\n",
len, ntohs(oh->length));
} else if (ntohs(oh->length) < len) {
ds_put_format(&string,