+static const char *
+ofputil_table_miss_to_string(enum ofputil_table_miss miss)
+{
+ switch (miss) {
+ case OFPUTIL_TABLE_MISS_DEFAULT: return "default";
+ case OFPUTIL_TABLE_MISS_CONTROLLER: return "controller";
+ case OFPUTIL_TABLE_MISS_CONTINUE: return "continue";
+ case OFPUTIL_TABLE_MISS_DROP: return "drop";
+ default: return "***error***";
+ }
+}
+
+static const char *
+ofputil_table_eviction_to_string(enum ofputil_table_eviction eviction)
+{
+ switch (eviction) {
+ case OFPUTIL_TABLE_EVICTION_DEFAULT: return "default";
+ case OFPUTIL_TABLE_EVICTION_ON: return "on";
+ case OFPUTIL_TABLE_EVICTION_OFF: return "off";
+ default: return "***error***";
+ }
+
+}
+
+static const char *
+ofputil_eviction_flag_to_string(uint32_t bit)
+{
+ enum ofp14_table_mod_prop_eviction_flag eviction_flag = bit;
+
+ switch (eviction_flag) {
+ case OFPTMPEF14_OTHER: return "OTHER";
+ case OFPTMPEF14_IMPORTANCE: return "IMPORTANCE";
+ case OFPTMPEF14_LIFETIME: return "LIFETIME";
+ }
+
+ return NULL;
+}
+
+/* Appends to 'string' a description of the bitmap of OFPTMPEF14_* values in
+ * 'eviction_flags'. */
+static void
+ofputil_put_eviction_flags(struct ds *string, uint32_t eviction_flags)
+{
+ if (eviction_flags != UINT32_MAX) {
+ ofp_print_bit_names(string, eviction_flags,
+ ofputil_eviction_flag_to_string, '|');
+ } else {
+ ds_put_cstr(string, "(default)");
+ }
+}
+
+static const char *
+ofputil_table_vacancy_to_string(enum ofputil_table_vacancy vacancy)
+{
+ switch (vacancy) {
+ case OFPUTIL_TABLE_VACANCY_DEFAULT: return "default";
+ case OFPUTIL_TABLE_VACANCY_ON: return "on";
+ case OFPUTIL_TABLE_VACANCY_OFF: return "off";
+ default: return "***error***";
+ }
+
+}
+
+static void
+ofp_print_table_mod(struct ds *string, const struct ofp_header *oh)
+{
+ struct ofputil_table_mod pm;
+ enum ofperr error;
+
+ error = ofputil_decode_table_mod(oh, &pm);
+ if (error) {
+ ofp_print_error(string, error);
+ return;
+ }
+
+ if (pm.table_id == 0xff) {
+ ds_put_cstr(string, " table_id: ALL_TABLES");
+ } else {
+ ds_put_format(string, " table_id=%"PRIu8, pm.table_id);
+ }
+
+ if (pm.miss != OFPUTIL_TABLE_MISS_DEFAULT) {
+ ds_put_format(string, ", flow_miss_config=%s",
+ ofputil_table_miss_to_string(pm.miss));
+ }
+ if (pm.eviction != OFPUTIL_TABLE_EVICTION_DEFAULT) {
+ ds_put_format(string, ", eviction=%s",
+ ofputil_table_eviction_to_string(pm.eviction));
+ }
+ if (pm.eviction_flags != UINT32_MAX) {
+ ds_put_cstr(string, "eviction_flags=");
+ ofputil_put_eviction_flags(string, pm.eviction_flags);
+ }
+ if (pm.vacancy != OFPUTIL_TABLE_VACANCY_DEFAULT) {
+ ds_put_format(string, ", vacancy=%s",
+ ofputil_table_vacancy_to_string(pm.vacancy));
+ if (pm.vacancy == OFPUTIL_TABLE_VACANCY_ON) {
+ ds_put_format(string, " vacancy:%"PRIu8""
+ ",%"PRIu8"", pm.table_vacancy.vacancy_down,
+ pm.table_vacancy.vacancy_up);
+ }
+ }
+}
+
+/* This function will print the Table description properties. */
+static void
+ofp_print_table_desc(struct ds *string, const struct ofputil_table_desc *td)
+{
+ ds_put_format(string, "\n table %"PRIu8, td->table_id);
+ ds_put_cstr(string, ":\n");
+ ds_put_format(string, " eviction=%s eviction_flags=",
+ ofputil_table_eviction_to_string(td->eviction));
+ ofputil_put_eviction_flags(string, td->eviction_flags);
+ ds_put_char(string, '\n');
+ ds_put_format(string, " vacancy=%s",
+ ofputil_table_vacancy_to_string(td->vacancy));
+ if (td->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
+ ds_put_format(string, " vacancy_down=%"PRIu8"%%",
+ td->table_vacancy.vacancy_down);
+ ds_put_format(string, " vacancy_up=%"PRIu8"%%",
+ td->table_vacancy.vacancy_up);
+ ds_put_format(string, " vacancy=%"PRIu8"%%",
+ td->table_vacancy.vacancy);
+ }
+ ds_put_char(string, '\n');
+}
+
+static void
+ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh)
+{
+ struct ofputil_table_status ts;
+ enum ofperr error;
+
+ error = ofputil_decode_table_status(oh, &ts);
+ if (error) {
+ ofp_print_error(string, error);
+ return;
+ }
+
+ if (ts.reason == OFPTR_VACANCY_DOWN) {
+ ds_put_format(string, " reason=VACANCY_DOWN");
+ } else if (ts.reason == OFPTR_VACANCY_UP) {
+ ds_put_format(string, " reason=VACANCY_UP");
+ }
+
+ ds_put_format(string, "\ntable_desc:-");
+ ofp_print_table_desc(string, &ts.desc);
+}
+
+static void
+ofp_print_queue_get_config_request(struct ds *string,
+ const struct ofp_header *oh)
+{
+ enum ofperr error;
+ ofp_port_t port;
+ uint32_t queue;
+
+ error = ofputil_decode_queue_get_config_request(oh, &port, &queue);
+ if (error) {
+ ofp_print_error(string, error);
+ return;
+ }
+
+ ds_put_cstr(string, " port=");
+ ofputil_format_port(port, string);
+
+ if (queue != OFPQ_ALL) {
+ ds_put_cstr(string, " queue=");
+ ofp_print_queue_name(string, queue);
+ }
+}
+
+static void
+print_queue_rate(struct ds *string, const char *name, unsigned int rate)
+{
+ if (rate <= 1000) {
+ ds_put_format(string, " %s:%u.%u%%", name, rate / 10, rate % 10);
+ } else if (rate < UINT16_MAX) {
+ ds_put_format(string, " %s:(disabled)", name);
+ }
+}
+
+static void
+ofp_print_queue_get_config_reply(struct ds *string,
+ const struct ofp_header *oh)
+{
+ struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
+ ofp_port_t port = 0;
+
+ ds_put_char(string, ' ');
+ for (;;) {
+ struct ofputil_queue_config queue;
+ int retval;
+
+ retval = ofputil_pull_queue_get_config_reply(&b, &queue);
+ if (retval) {
+ if (retval != EOF) {
+ ofp_print_error(string, retval);
+ }
+ ds_chomp(string, ' ');
+ break;
+ }
+
+ if (queue.port != port) {
+ port = queue.port;
+
+ ds_put_cstr(string, "port=");
+ ofputil_format_port(port, string);
+ ds_put_char(string, '\n');
+ }
+
+ ds_put_format(string, "queue %"PRIu32":", queue.queue);
+ print_queue_rate(string, "min_rate", queue.min_rate);
+ print_queue_rate(string, "max_rate", queue.max_rate);
+ ds_put_char(string, '\n');
+ }
+}
+