* derivatives without specific, written prior permission.
*/
+#include <config.h>
#include "ofp-print.h"
#include "xtoxll.h"
if (ntohs(op->total_len) != data_len)
ds_put_format(string, " (***total_len != data_len***)");
} else {
- ds_put_format(string, " buffer=%08"PRIx32, ntohl(op->buffer_id));
+ ds_put_format(string, " buffer=0x%08"PRIx32, ntohl(op->buffer_id));
if (ntohs(op->total_len) < data_len)
ds_put_format(string, " (***total_len < data_len***)");
}
{
const char *name;
switch (port) {
+ case OFPP_IN_PORT:
+ name = "IN_PORT";
+ break;
case OFPP_TABLE:
name = "TABLE";
break;
break;
case OFPAT_SET_NW_SRC:
- ds_put_format(string, "mod_nw_src:"IP_FMT, IP_ARGS(a->arg.nw_addr));
+ ds_put_format(string, "mod_nw_src:"IP_FMT, IP_ARGS(&a->arg.nw_addr));
break;
case OFPAT_SET_NW_DST:
- ds_put_format(string, "mod_nw_dst:"IP_FMT, IP_ARGS(a->arg.nw_addr));
+ ds_put_format(string, "mod_nw_dst:"IP_FMT, IP_ARGS(&a->arg.nw_addr));
break;
case OFPAT_SET_TP_SRC:
int verbosity)
{
const struct ofp_packet_out *opo = oh;
+ int n_actions = ntohs(opo->n_actions);
+ int act_len = n_actions * sizeof opo->actions[0];
ds_put_cstr(string, " in_port=");
ofp_print_port_name(string, ntohs(opo->in_port));
+ ds_put_format(string, " n_actions=%d ", n_actions);
+ if (act_len > (ntohs(opo->header.length) - sizeof *opo)) {
+ ds_put_format(string, "***packet too short for number of actions***\n");
+ return;
+ }
+ ofp_print_actions(string, opo->actions, act_len);
+
if (ntohl(opo->buffer_id) == UINT32_MAX) {
- ds_put_cstr(string, " out_port=");
- ofp_print_port_name(string, ntohs(opo->out_port));
+ int data_len = len - sizeof *opo - act_len;
+ ds_put_format(string, " data_len=%d", data_len);
if (verbosity > 0 && len > sizeof *opo) {
- char *packet = ofp_packet_to_string(opo->u.data, len - sizeof *opo,
- len - sizeof *opo);
+ char *packet = ofp_packet_to_string(&opo->actions[n_actions],
+ data_len, data_len);
ds_put_char(string, '\n');
ds_put_cstr(string, packet);
free(packet);
}
} else {
- ds_put_format(string, " buffer=%08"PRIx32, ntohl(opo->buffer_id));
- ofp_print_actions(string, opo->u.actions, len - sizeof *opo);
+ ds_put_format(string, " buffer=0x%08"PRIx32, ntohl(opo->buffer_id));
}
ds_put_char(string, '\n');
}
ds_put_format(string, " (sending flow expirations)");
}
if (flags) {
- ds_put_format(string, " ***unknown flags %04"PRIx16"***", flags);
+ ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***", flags);
}
ds_put_format(string, " miss_send_len=%"PRIu16"\n", ntohs(osc->miss_send_len));
} else {
ds_put_char(string, '*');
}
+ ds_put_char(string, ',');
}
/* Pretty-print the ofp_match structure */
uint16_t w = ntohs(om->wildcards);
print_wild(f, "in_port=", w & OFPFW_IN_PORT, verbosity,
- "%d,", ntohs(om->in_port));
+ "%d", ntohs(om->in_port));
print_wild(f, "dl_vlan=", w & OFPFW_DL_VLAN, verbosity,
- "%04x,", ntohs(om->dl_vlan));
+ "0x%04x", ntohs(om->dl_vlan));
print_wild(f, "dl_src=", w & OFPFW_DL_SRC, verbosity,
- ETH_ADDR_FMT",", ETH_ADDR_ARGS(om->dl_src));
+ ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_src));
print_wild(f, "dl_dst=", w & OFPFW_DL_DST, verbosity,
- ETH_ADDR_FMT",", ETH_ADDR_ARGS(om->dl_dst));
+ ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_dst));
print_wild(f, "dl_type=", w & OFPFW_DL_TYPE, verbosity,
- "%04x,", ntohs(om->dl_type));
+ "0x%04x", ntohs(om->dl_type));
print_wild(f, "nw_src=", w & OFPFW_NW_SRC, verbosity,
- IP_FMT",", IP_ARGS(&om->nw_src));
+ IP_FMT, IP_ARGS(&om->nw_src));
print_wild(f, "nw_dst=", w & OFPFW_NW_DST, verbosity,
- IP_FMT",", IP_ARGS(&om->nw_dst));
+ IP_FMT, IP_ARGS(&om->nw_dst));
print_wild(f, "nw_proto=", w & OFPFW_NW_PROTO, verbosity,
- "%u,", om->nw_proto);
+ "%u", om->nw_proto);
print_wild(f, "tp_src=", w & OFPFW_TP_SRC, verbosity,
- "%d,", ntohs(om->tp_src));
+ "%d", ntohs(om->tp_src));
print_wild(f, "tp_dst=", w & OFPFW_TP_DST, verbosity,
- "%d,", ntohs(om->tp_dst));
+ "%d", ntohs(om->tp_dst));
}
/* Pretty-print the OFPT_FLOW_MOD packet of 'len' bytes at 'oh' to 'string'
const struct ofp_flow_mod *ofm = oh;
ofp_print_match(string, &ofm->match, verbosity);
- ds_put_format(string, " cmd:%d idle:%d pri:%d buf:%#x",
- ntohs(ofm->command), ntohs(ofm->max_idle),
+ ds_put_format(string, " cmd:%d idle:%d hard:%d pri:%d buf:%#x",
+ ntohs(ofm->command), ntohs(ofm->idle_timeout),
+ ntohs(ofm->hard_timeout),
ofm->match.wildcards ? ntohs(ofm->priority) : (uint16_t)-1,
ntohl(ofm->buffer_id));
ofp_print_actions(string, ofm->actions,
const struct ofp_flow_expired *ofe = oh;
ofp_print_match(string, &ofe->match, verbosity);
+ ds_put_cstr(string, " reason=");
+ switch (ofe->reason) {
+ case OFPER_IDLE_TIMEOUT:
+ ds_put_cstr(string, "idle");
+ break;
+ case OFPER_HARD_TIMEOUT:
+ ds_put_cstr(string, "hard");
+ break;
+ default:
+ ds_put_format(string, "**%"PRIu8"**", ofe->reason);
+ break;
+ }
ds_put_format(string,
" pri%"PRIu16" secs%"PRIu32" pkts%"PRIu64" bytes%"PRIu64"\n",
ofe->match.wildcards ? ntohs(ofe->priority) : (uint16_t)-1,
ofp_print_phy_port(string, &ops->desc);
}
+static void
+ofp_version_stats_reply(struct ds *string, const void *body, size_t len,
+ int verbosity)
+{
+ const struct ofp_version_stats *vs = body;
+
+ ds_put_format(string, "Manufacturer: %s\n", vs->mfr_desc);
+ ds_put_format(string, "Hardware: %s\n", vs->hw_desc);
+ ds_put_format(string, "Software: %s\n", vs->sw_desc);
+}
+
static void
ofp_flow_stats_request(struct ds *string, const void *oh, size_t len,
int verbosity)
ds_put_format(string, "n_packets=%"PRIu64", ",
ntohll(fs->packet_count));
ds_put_format(string, "n_bytes=%"PRIu64", ", ntohll(fs->byte_count));
- ds_put_format(string, "max_idle=%"PRIu16",", ntohs(fs->max_idle));
+ ds_put_format(string, "idle_timeout=%"PRIu16",",
+ ntohs(fs->idle_timeout));
+ ds_put_format(string, "hard_timeout=%"PRIu16",",
+ ntohs(fs->hard_timeout));
ofp_print_match(string, &fs->match, verbosity);
ofp_print_actions(string, fs->actions, length - sizeof *fs);
ds_put_char(string, '\n');
ds_put_format(string, " flow_count=%"PRIu32, ntohl(asr->flow_count));
}
+static void print_port_stat(struct ds *string, const char *leader,
+ uint64_t stat, int more)
+{
+ ds_put_cstr(string, leader);
+ if (stat != -1) {
+ ds_put_format(string, "%"PRIu64, stat);
+ } else {
+ ds_put_char(string, '?');
+ }
+ if (more) {
+ ds_put_cstr(string, ", ");
+ } else {
+ ds_put_cstr(string, "\n");
+ }
+}
+
static void
ofp_port_stats_reply(struct ds *string, const void *body, size_t len,
int verbosity)
}
for (; n--; ps++) {
- ds_put_format(string, " port %"PRIu16": ", ntohs(ps->port_no));
- ds_put_format(string, "rx %"PRIu64", ", ntohll(ps->rx_count));
- ds_put_format(string, "tx %"PRIu64", ", ntohll(ps->tx_count));
- ds_put_format(string, "dropped %"PRIu64"\n", ntohll(ps->drop_count));
+ ds_put_format(string, " port %2"PRIu16": ", ntohs(ps->port_no));
+
+ ds_put_cstr(string, "rx ");
+ print_port_stat(string, "pkts=", ntohll(ps->rx_packets), 1);
+ print_port_stat(string, "bytes=", ntohll(ps->rx_bytes), 1);
+ print_port_stat(string, "drop=", ntohll(ps->rx_dropped), 1);
+ print_port_stat(string, "errs=", ntohll(ps->rx_errors), 1);
+ print_port_stat(string, "frame=", ntohll(ps->rx_frame_err), 1);
+ print_port_stat(string, "over=", ntohll(ps->rx_over_err), 1);
+ print_port_stat(string, "crc=", ntohll(ps->rx_crc_err), 0);
+
+ ds_put_cstr(string, " tx ");
+ print_port_stat(string, "pkts=", ntohll(ps->tx_packets), 1);
+ print_port_stat(string, "bytes=", ntohll(ps->tx_bytes), 1);
+ print_port_stat(string, "drop=", ntohll(ps->tx_dropped), 1);
+ print_port_stat(string, "errs=", ntohll(ps->tx_errors), 1);
+ print_port_stat(string, "coll=", ntohll(ps->collisions), 0);
}
}
};
static const struct stats_type stats_types[] = {
+ [OFPST_VERSION] = {
+ "version",
+ { 0, 0, NULL },
+ { 0, SIZE_MAX, ofp_version_stats_reply },
+ },
[OFPST_FLOW] = {
"flow",
{ sizeof(struct ofp_flow_stats_request),
const struct ofp_stats_request *srq = oh;
if (srq->flags) {
- ds_put_format(string, " ***unknown flags %04"PRIx16"***",
+ ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***",
ntohs(srq->flags));
}
flags &= ~OFPSF_REPLY_MORE;
}
if (flags) {
- ds_put_format(string, "[***unknown%04"PRIx16"***]", flags);
+ ds_put_format(string, "[***unknown flags 0x%04"PRIx16"***]", flags);
}
}
verbosity, REPLY);
}
+static void
+ofp_echo(struct ds *string, const void *oh, size_t len, int verbosity)
+{
+ const struct ofp_header *hdr = oh;
+
+ ds_put_format(string, " %zu bytes of payload\n", len - sizeof *hdr);
+ if (verbosity > 1) {
+ ds_put_hex_dump(string, hdr, len - sizeof *hdr, 0, true);
+ }
+}
+
struct openflow_packet {
const char *name;
size_t min_size;
sizeof (struct ofp_stats_reply),
ofp_stats_reply,
},
+ [OFPT_ECHO_REQUEST] = {
+ "echo_request",
+ sizeof (struct ofp_header),
+ ofp_echo,
+ },
+ [OFPT_ECHO_REPLY] = {
+ "echo_reply",
+ sizeof (struct ofp_header),
+ ofp_echo,
+ },
};
/* Composes and returns a string representing the OpenFlow packet of 'len'
}
pkt = &packets[oh->type];
- ds_put_format(&string, "%s (xid=%"PRIx32"):", pkt->name, oh->xid);
+ ds_put_format(&string, "%s (xid=0x%"PRIx32"):", pkt->name, oh->xid);
if (ntohs(oh->length) > len)
ds_put_format(&string, " (***truncated to %zu bytes from %"PRIu16"***)",