return ap < bp ? -1 : ap > bp;
}
+static void ofp_print_port_features(struct ds *string, uint32_t features)
+{
+ if (features == 0) {
+ ds_put_cstr(string, "Unsupported\n");
+ return;
+ }
+ if (features & OFPPF_10MB_HD) {
+ ds_put_cstr(string, "10MB-HD ");
+ }
+ if (features & OFPPF_10MB_FD) {
+ ds_put_cstr(string, "10MB-FD ");
+ }
+ if (features & OFPPF_100MB_HD) {
+ ds_put_cstr(string, "100MB-HD ");
+ }
+ if (features & OFPPF_100MB_FD) {
+ ds_put_cstr(string, "100MB-FD ");
+ }
+ if (features & OFPPF_1GB_HD) {
+ ds_put_cstr(string, "1GB-HD ");
+ }
+ if (features & OFPPF_1GB_FD) {
+ ds_put_cstr(string, "1GB-FD ");
+ }
+ if (features & OFPPF_10GB_FD) {
+ ds_put_cstr(string, "10GB-FD ");
+ }
+ if (features & OFPPF_COPPER) {
+ ds_put_cstr(string, "COPPER ");
+ }
+ if (features & OFPPF_FIBER) {
+ ds_put_cstr(string, "FIBER ");
+ }
+ if (features & OFPPF_AUTONEG) {
+ ds_put_cstr(string, "AUTO_NEG ");
+ }
+ if (features & OFPPF_PAUSE) {
+ ds_put_cstr(string, "AUTO_PAUSE ");
+ }
+ if (features & OFPPF_PAUSE_ASYM) {
+ ds_put_cstr(string, "AUTO_PAUSE_ASYM ");
+ }
+ ds_put_char(string, '\n');
+}
+
static void
ofp_print_phy_port(struct ds *string, const struct ofp_phy_port *port)
{
ds_put_char(string, ' ');
ofp_print_port_name(string, ntohs(port->port_no));
- ds_put_format(string, "(%s): addr:"ETH_ADDR_FMT", speed:%d, flags:%#x, "
- "feat:%#x\n", name,
- ETH_ADDR_ARGS(port->hw_addr), ntohl(port->speed),
- ntohl(port->flags), ntohl(port->features));
+ ds_put_format(string, "(%s): addr:"ETH_ADDR_FMT", config: %#x, state:%#x\n",
+ name, ETH_ADDR_ARGS(port->hw_addr), ntohl(port->config),
+ ntohl(port->state));
+ if (port->curr) {
+ ds_put_format(string, " current: ");
+ ofp_print_port_features(string, ntohl(port->curr));
+ }
+ if (port->advertised) {
+ ds_put_format(string, " advertised: ");
+ ofp_print_port_features(string, ntohl(port->advertised));
+ }
+ if (port->supported) {
+ ds_put_format(string, " supported: ");
+ ofp_print_port_features(string, ntohl(port->supported));
+ }
+ if (port->peer) {
+ ds_put_format(string, " peer: ");
+ ofp_print_port_features(string, ntohl(port->peer));
+ }
}
/* Pretty-print the struct ofp_switch_features of 'len' bytes at 'oh' to
int i;
ds_put_format(string, "dp id:%"PRIx64"\n", ntohll(osf->datapath_id));
- ds_put_format(string, "tables: exact:%d, compressed:%d, general:%d\n",
- ntohl(osf->n_exact),
- ntohl(osf->n_compression), ntohl(osf->n_general));
- ds_put_format(string, "buffers: size:%d, number:%d\n",
- ntohl(osf->buffer_mb), ntohl(osf->n_buffers));
+ ds_put_format(string, "n_tables:%d, n_buffers:%d\n", osf->n_tables,
+ ntohl(osf->n_buffers));
ds_put_format(string, "features: capabilities:%#x, actions:%#x\n",
ntohl(osf->capabilities), ntohl(osf->actions));
const struct ofp_flow_mod *ofm = oh;
ofp_print_match(string, &ofm->match, verbosity);
- 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),
+ switch (ntohs(ofm->command)) {
+ case OFPFC_ADD:
+ ds_put_cstr(string, " ADD: ");
+ break;
+ case OFPFC_MODIFY:
+ ds_put_cstr(string, " MOD: ");
+ break;
+ case OFPFC_MODIFY_STRICT:
+ ds_put_cstr(string, " MOD_STRICT: ");
+ break;
+ case OFPFC_DELETE:
+ ds_put_cstr(string, " DEL: ");
+ break;
+ case OFPFC_DELETE_STRICT:
+ ds_put_cstr(string, " DEL_STRICT: ");
+ break;
+ default:
+ ds_put_format(string, " cmd:%d ", ntohs(ofm->command));
+ }
+ ds_put_format(string, "idle:%d hard:%d pri:%d buf:%#x",
+ 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,
ntohll(ofe->byte_count));
}
-/* Pretty-print the OFPT_ERROR_MSG packet of 'len' bytes at 'oh' to 'string'
+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),
+};
+#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 "?";
+}
+
+/* Pretty-print the OFPT_ERROR packet of 'len' bytes at 'oh' to 'string'
* at the given 'verbosity' level. */
static void
ofp_print_error_msg(struct ds *string, const void *oh, size_t len,
int verbosity)
{
const struct ofp_error_msg *oem = oh;
+ int type = ntohs(oem->type);
+ int code = ntohs(oem->code);
+ char *s;
- ds_put_format(string,
- " type%d code%d\n", ntohs(oem->type), ntohs(oem->code));
+ ds_put_format(string, " type%d(%s) code%d(%s) payload:\n",
+ type, lookup_error_type(type),
+ code, lookup_error_code(type, code));
+
+ switch (type) {
+ case OFPET_HELLO_FAILED:
+ ds_put_printable(string, (char *) oem->data, len - sizeof *oem);
+ break;
+
+ case OFPET_BAD_REQUEST:
+ s = ofp_to_string(oem->data, len - sizeof *oem, 1);
+ ds_put_cstr(string, s);
+ free(s);
+ break;
+
+ default:
+ ds_put_hex_dump(string, oem->data, len - sizeof *oem, 0, true);
+ break;
+ }
}
/* Pretty-print the OFPT_PORT_STATUS packet of 'len' bytes at 'oh' to 'string'
const struct ofp_port_status *ops = oh;
if (ops->reason == OFPPR_ADD) {
- ds_put_format(string, "add:");
+ ds_put_format(string, " ADD:");
} else if (ops->reason == OFPPR_DELETE) {
- ds_put_format(string, "del:");
- } else if (ops->reason == OFPPR_MOD) {
- ds_put_format(string, "mod:");
- } else {
- ds_put_format(string, "err:");
+ ds_put_format(string, " DEL:");
+ } else if (ops->reason == OFPPR_MODIFY) {
+ ds_put_format(string, " MOD:");
}
ofp_print_phy_port(string, &ops->desc);
strncpy(name, ts->name, sizeof name);
name[OFP_MAX_TABLE_NAME_LEN] = '\0';
- ds_put_format(string, " table %"PRIu8": ", ts->table_id);
- ds_put_format(string, "name %-8s, ", name);
- ds_put_format(string, "max %6"PRIu32", ", ntohl(ts->max_entries));
- ds_put_format(string, "active %6"PRIu32", ", ntohl(ts->active_count));
- ds_put_format(string, "matched %6"PRIu64"\n",
- ntohll(ts->matched_count));
+ ds_put_format(string, " %d: %-8s: ", ts->table_id, name);
+ ds_put_format(string, "wild=0x%05"PRIx32", ", ntohl(ts->wildcards));
+ ds_put_format(string, "max=%6"PRIu32", ", ntohl(ts->max_entries));
+ ds_put_format(string, "active=%"PRIu32"\n", ntohl(ts->active_count));
+ ds_put_cstr(string, " ");
+ ds_put_format(string, "lookup=%"PRIu64", ",
+ ntohll(ts->lookup_count));
+ ds_put_format(string, "matched=%"PRIu64"\n",
+ ntohll(ts->matched_count));
}
}
static void
-switch_status_reply(struct ds *string, const void *body, size_t len,
- int verbosity UNUSED)
+vendor_stat(struct ds *string, const void *body, size_t len,
+ int verbosity UNUSED)
{
- char *save_ptr = NULL;
- char *s, *line;
-
- s = xmemdup0(body, len);
- for (line = strtok_r(s, "\n\n", &save_ptr); line != NULL;
- line = strtok_r(NULL, "\n\n", &save_ptr)) {
- ds_put_printable(string, line, strlen(line));
- ds_put_char(string, '\n');
- }
- free(s);
+ ds_put_format(string, " vendor=%08"PRIx32, ntohl(*(uint32_t *) body));
+ ds_put_format(string, " %zu bytes additional data",
+ len - sizeof(uint32_t));
}
enum stats_direction {
{ 0, SIZE_MAX, ofp_port_stats_reply },
},
{
- OFPST_SWITCH,
- "switch status",
- { 0, 0, NULL, },
- { 0, SIZE_MAX, switch_status_reply },
+ OFPST_VENDOR,
+ "vendor-specific",
+ { sizeof(uint32_t), SIZE_MAX, vendor_stat },
+ { sizeof(uint32_t), SIZE_MAX, vendor_stat },
},
{
-1,
};
static const struct openflow_packet packets[] = {
+ {
+ OFPT_HELLO,
+ "hello",
+ sizeof (struct ofp_header),
+ NULL,
+ },
{
OFPT_FEATURES_REQUEST,
"features_request",
OFPT_PORT_MOD,
"port_mod",
sizeof (struct ofp_port_mod),
- NULL,
+ ofp_print_port_mod,
},
{
OFPT_PORT_STATUS,
ofp_print_port_status
},
{
- OFPT_ERROR_MSG,
+ OFPT_ERROR,
"error_msg",
sizeof (struct ofp_error_msg),
ofp_print_error_msg,