ofp-print: Print OFPUTIL_NXST_AGGREGATE_REPLY.
[openvswitch] / lib / ofp-print.c
index 4141b9f9b0e0a50d70b6e2e419ddcfa95efc571a..56111435328e228d72b5762327a80c91fbb5489a 100644 (file)
@@ -298,6 +298,10 @@ ofp_print_action(struct ds *string, const struct ofp_action_header *ah,
         [OFPAT_SET_TP_DST] = {
             sizeof(struct ofp_action_tp_port),
             sizeof(struct ofp_action_tp_port),
+        },
+        [OFPAT_ENQUEUE] = {
+            sizeof(struct ofp_action_enqueue),
+            sizeof(struct ofp_action_enqueue),
         }
         /* OFPAT_VENDOR is not here, since it would blow up the array size. */
     };
@@ -848,6 +852,19 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh,
                       fm.n_actions * sizeof *fm.actions);
 }
 
+static void
+ofp_print_duration(struct ds *string, unsigned int sec, unsigned int nsec)
+{
+    ds_put_format(string, "%u", sec);
+    if (nsec > 0) {
+        ds_put_format(string, ".%09u", nsec);
+        while (string->string[string->length - 1] == '0') {
+            string->length--;
+        }
+    }
+    ds_put_char(string, 's');
+}
+
 static void
 ofp_print_flow_removed(struct ds *string, const struct ofp_flow_removed *ofr,
                        int verbosity)
@@ -875,9 +892,10 @@ ofp_print_flow_removed(struct ds *string, const struct ofp_flow_removed *ofr,
     if (ofr->priority != htons(32768)) {
         ds_put_format(string, " pri:%"PRIu16, ntohs(ofr->priority));
     }
-    ds_put_format(string, " secs%"PRIu32" nsecs%"PRIu32
-         " idle%"PRIu16" pkts%"PRIu64" bytes%"PRIu64"\n",
-         ntohl(ofr->duration_sec), ntohl(ofr->duration_nsec),
+    ds_put_cstr(string, " duration");
+    ofp_print_duration(string,
+                       ntohl(ofr->duration_sec), ntohl(ofr->duration_nsec));
+    ds_put_format(string, " idle%"PRIu16" pkts%"PRIu64" bytes%"PRIu64"\n",
          ntohs(ofr->idle_timeout), ntohll(ofr->packet_count),
          ntohll(ofr->byte_count));
 }
@@ -919,6 +937,13 @@ static const struct error_type error_types[] = {
     ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN),
     ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BUFFER_EMPTY),
     ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BUFFER_UNKNOWN),
+    /* Nicira error extensions. */
+    ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_INVALID),
+    ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_TYPE),
+    ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_VALUE),
+    ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_MASK),
+    ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_BAD_PREREQ),
+    ERROR_CODE(OFPET_BAD_REQUEST, NXBRC_NXM_DUP_TYPE),
 
     ERROR_TYPE(OFPET_BAD_ACTION),
     ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_TYPE),
@@ -936,6 +961,9 @@ static const struct error_type error_types[] = {
     ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_EPERM),
     ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_EMERG_TIMEOUT),
     ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_COMMAND),
+    /* Nicira error extenstions. */
+    ERROR_CODE(OFPET_FLOW_MOD_FAILED, NXFMFC_HARDWARE),
+    ERROR_CODE(OFPET_FLOW_MOD_FAILED, NXFMFC_BAD_TABLE_ID),
 
     ERROR_TYPE(OFPET_PORT_MOD_FAILED),
     ERROR_CODE(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_PORT),
@@ -982,6 +1010,24 @@ ofp_print_error(struct ds *string, int error)
                   code, lookup_error_code(type, code));
 }
 
+static void
+ofp_print_nx_error_msg(struct ds *string, const struct ofp_error_msg *oem)
+{
+    size_t len = ntohs(oem->header.length);
+    const struct nx_vendor_error *nve = (struct nx_vendor_error *)oem->data;
+    int vendor = ntohl(nve->vendor);
+    int type = ntohs(nve->type);
+    int code = ntohs(nve->code);
+
+    ds_put_format(string, " vendor:%x type:%d(%s) code:%d(%s) payload:\n",
+                  vendor,
+                  type, lookup_error_type(type),
+                  code, lookup_error_code(type, code));
+
+    ds_put_hex_dump(string, nve + 1, len - sizeof *oem - sizeof *nve,
+                    0, true);
+}
+
 static void
 ofp_print_error_msg(struct ds *string, const struct ofp_error_msg *oem)
 {
@@ -990,6 +1036,19 @@ ofp_print_error_msg(struct ds *string, const struct ofp_error_msg *oem)
     int code = ntohs(oem->code);
     char *s;
 
+
+    if (type == NXET_VENDOR && code == NXVC_VENDOR_ERROR) {
+        if (len < sizeof *oem + sizeof(struct nx_vendor_error)) {
+            ds_put_format(string,
+                          "(***truncated extended error message is %zu bytes "
+                          "when it should be at least %zu***)\n",
+                          len, sizeof(struct nx_vendor_error));
+            return;
+        }
+
+        return ofp_print_nx_error_msg(string, oem);
+    }
+
     ds_put_format(string, " type:%d(%s) code:%d(%s) payload:\n",
                   type, lookup_error_type(type),
                   code, lookup_error_code(type, code));
@@ -1043,18 +1102,28 @@ ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh)
 }
 
 static void
-ofp_print_ofpst_flow_request(struct ds *string, const struct ofp_header *oh,
-                             int verbosity)
+ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh)
 {
-    const struct ofp_flow_stats_request *fsr = ofputil_stats_body(oh);
+    struct flow_stats_request fsr;
+    int error;
 
-    if (fsr->table_id == 0xff) {
-        ds_put_format(string, " table_id=any, ");
-    } else {
-        ds_put_format(string, " table_id=%"PRIu8", ", fsr->table_id);
+    error = ofputil_decode_flow_stats_request(&fsr, oh, NXFF_OPENFLOW10);
+    if (error) {
+        ofp_print_error(string, error);
+        return;
     }
 
-    ofp_print_match(string, &fsr->match, verbosity);
+    if (fsr.table_id != 0xff) {
+        ds_put_format(string, " table_id=%"PRIu8, fsr.table_id);
+    }
+
+    if (fsr.out_port != OFPP_NONE) {
+        ds_put_cstr(string, " out_port=");
+        ofp_print_port_name(string, fsr.out_port);
+    }
+
+    ds_put_char(string, ' ');
+    cls_rule_format(&fsr.match, string);
 }
 
 static void
@@ -1099,14 +1168,12 @@ ofp_print_ofpst_flow_reply(struct ds *string, const struct ofp_header *oh,
             break;
         }
 
-        ds_put_format(string, "  cookie=0x%"PRIx64", ", ntohll(fs->cookie));
-        ds_put_format(string, "duration_sec=%"PRIu32"s, ",
-                    ntohl(fs->duration_sec));
-        ds_put_format(string, "duration_nsec=%"PRIu32"ns, ",
-                    ntohl(fs->duration_nsec));
-        ds_put_format(string, "table_id=%"PRIu8", ", fs->table_id);
-        ds_put_format(string, "priority=%"PRIu16", ",
-                    fs->match.wildcards ? ntohs(fs->priority) : (uint16_t)-1);
+        ds_put_format(string, " cookie=0x%"PRIx64", duration=",
+                      ntohll(fs->cookie));
+        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));
@@ -1119,6 +1186,7 @@ ofp_print_ofpst_flow_reply(struct ds *string, const struct ofp_header *oh,
                           ntohs(fs->hard_timeout));
         }
         ofp_print_match(string, &fs->match, verbosity);
+        ds_put_char(string, ' ');
         ofp_print_actions(string, fs->actions, length - sizeof *fs);
 
         pos += length;
@@ -1126,30 +1194,102 @@ ofp_print_ofpst_flow_reply(struct ds *string, const struct ofp_header *oh,
 }
 
 static void
-ofp_print_ofpst_aggregate_request(struct ds *string,
-                                  const struct ofp_header *oh, int verbosity)
+ofp_print_nxst_flow_reply(struct ds *string, const struct ofp_header *oh)
 {
-    const struct ofp_aggregate_stats_request *asr = ofputil_stats_body(oh);
+    struct ofpbuf b;
+
+    ofpbuf_use_const(&b, ofputil_nxstats_body(oh),
+                     ofputil_nxstats_body_len(oh));
+    while (b.size > 0) {
+        const struct nx_flow_stats *fs;
+        union ofp_action *actions;
+        struct cls_rule rule;
+        size_t actions_len, n_actions;
+        size_t length;
+        int match_len;
+        int error;
 
-    if (asr->table_id == 0xff) {
-        ds_put_format(string, " table_id=any, ");
-    } else {
-        ds_put_format(string, " table_id=%"PRIu8", ", asr->table_id);
-    }
+        fs = ofpbuf_try_pull(&b, sizeof *fs);
+        if (!fs) {
+            ds_put_format(string, " ***%td leftover bytes at end***", b.size);
+            break;
+        }
+
+        length = ntohs(fs->length);
+        if (length < sizeof *fs) {
+            ds_put_format(string, " ***nx_flow_stats claims length %zu***",
+                          length);
+            break;
+        }
+
+        match_len = ntohs(fs->match_len);
+        if (match_len > length - sizeof *fs) {
+            ds_put_format(string, " ***length=%zu match_len=%d***",
+                          length, match_len);
+            break;
+        }
+
+        ds_put_format(string, " cookie=0x%"PRIx64", duration=",
+                      ntohll(fs->cookie));
+        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));
+        if (fs->idle_timeout != htons(OFP_FLOW_PERMANENT)) {
+            ds_put_format(string, "idle_timeout=%"PRIu16",",
+                          ntohs(fs->idle_timeout));
+        }
+        if (fs->hard_timeout != htons(OFP_FLOW_PERMANENT)) {
+            ds_put_format(string, "hard_timeout=%"PRIu16",",
+                          ntohs(fs->hard_timeout));
+        }
+
+        error = nx_pull_match(&b, match_len, ntohs(fs->priority), &rule);
+        if (error) {
+            ofp_print_error(string, error);
+            break;
+        }
 
-    ofp_print_match(string, &asr->match, verbosity);
+        actions_len = length - sizeof *fs - ROUND_UP(match_len, 8);
+        error = ofputil_pull_actions(&b, actions_len, &actions, &n_actions);
+        if (error) {
+            ofp_print_error(string, error);
+            break;
+        }
+
+        cls_rule_format(&rule, string);
+        ds_put_char(string, ' ');
+        ofp_print_actions(string, (const struct ofp_action_header *) actions,
+                          n_actions * sizeof *actions);
+        ds_put_char(string, '\n');
+     }
 }
 
 static void
-ofp_print_ofpst_aggregate_reply(struct ds *string, const struct ofp_header *oh)
+ofp_print_ofp_aggregate_stats_reply (
+    struct ds *string, const struct ofp_aggregate_stats_reply *asr)
 {
-    const struct ofp_aggregate_stats_reply *asr = ofputil_stats_body(oh);
-
     ds_put_format(string, " packet_count=%"PRIu64, ntohll(asr->packet_count));
     ds_put_format(string, " byte_count=%"PRIu64, ntohll(asr->byte_count));
     ds_put_format(string, " flow_count=%"PRIu32, ntohl(asr->flow_count));
 }
 
+static void
+ofp_print_ofpst_aggregate_reply(struct ds *string, const struct ofp_header *oh)
+{
+    ofp_print_ofp_aggregate_stats_reply(string, ofputil_stats_body(oh));
+}
+
+static void
+ofp_print_nxst_aggregate_reply(struct ds *string,
+                               const struct nx_aggregate_stats_reply *nasr)
+{
+    ofp_print_ofp_aggregate_stats_reply(string, &nasr->asr);
+}
+
 static void print_port_stat(struct ds *string, const char *leader,
                             uint64_t stat, int more)
 {
@@ -1322,6 +1462,18 @@ ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity)
     }
 }
 
+static void
+ofp_print_nxt_status_message(struct ds *string, const struct ofp_header *oh)
+{
+    struct ofpbuf b;
+
+    ofpbuf_use_const(&b, oh, ntohs(oh->length));
+    ofpbuf_pull(&b, sizeof *oh);
+    ds_put_char(string, '"');
+    ds_put_printable(string, b.data, b.size);
+    ds_put_char(string, '"');
+}
+
 static void
 ofp_print_nxt_tun_id_from_cookie(struct ds *string,
                                  const struct nxt_tun_id_cookie *ntic)
@@ -1329,6 +1481,24 @@ ofp_print_nxt_tun_id_from_cookie(struct ds *string,
     ds_put_format(string, " set=%"PRIu8, ntic->set);
 }
 
+static void
+ofp_print_nxt_role_message(struct ds *string,
+                           const struct nx_role_request *nrr)
+{
+    unsigned int role = ntohl(nrr->role);
+
+    ds_put_cstr(string, " role=");
+    if (role == NX_ROLE_OTHER) {
+        ds_put_cstr(string, "other");
+    } else if (role == NX_ROLE_MASTER) {
+        ds_put_cstr(string, "master");
+    } else if (role == NX_ROLE_SLAVE) {
+        ds_put_cstr(string, "slave");
+    } else {
+        ds_put_format(string, "%u", role);
+    }
+}
+
 static void
 ofp_print_nxt_set_flow_format(struct ds *string,
                               const struct nxt_set_flow_format *nsff)
@@ -1424,13 +1594,11 @@ ofp_to_string__(const struct ofp_header *oh,
         break;
 
     case OFPUTIL_OFPST_FLOW_REQUEST:
-        ofp_print_stats_request(string, oh);
-        ofp_print_ofpst_flow_request(string, oh, verbosity);
-        break;
-
+    case OFPUTIL_NXST_FLOW_REQUEST:
     case OFPUTIL_OFPST_AGGREGATE_REQUEST:
+    case OFPUTIL_NXST_AGGREGATE_REQUEST:
         ofp_print_stats_request(string, oh);
-        ofp_print_ofpst_aggregate_request(string, oh, verbosity);
+        ofp_print_flow_stats_request(string, oh);
         break;
 
     case OFPUTIL_OFPST_TABLE_REQUEST:
@@ -1479,7 +1647,7 @@ ofp_to_string__(const struct ofp_header *oh,
 
     case OFPUTIL_NXT_STATUS_REQUEST:
     case OFPUTIL_NXT_STATUS_REPLY:
-        /* XXX */
+        ofp_print_nxt_status_message(string, oh);
         break;
 
     case OFPUTIL_NXT_TUN_ID_FROM_COOKIE:
@@ -1488,7 +1656,7 @@ ofp_to_string__(const struct ofp_header *oh,
 
     case OFPUTIL_NXT_ROLE_REQUEST:
     case OFPUTIL_NXT_ROLE_REPLY:
-        /* XXX */
+        ofp_print_nxt_role_message(string, msg);
         break;
 
     case OFPUTIL_NXT_SET_FLOW_FORMAT:
@@ -1500,11 +1668,16 @@ ofp_to_string__(const struct ofp_header *oh,
         break;
 
     case OFPUTIL_NXT_FLOW_REMOVED:
-    case OFPUTIL_NXST_FLOW_REQUEST:
-    case OFPUTIL_NXST_AGGREGATE_REQUEST:
+        /* XXX */
+        break;
+
     case OFPUTIL_NXST_FLOW_REPLY:
+        ofp_print_nxst_flow_reply(string, oh);
+        break;
+
     case OFPUTIL_NXST_AGGREGATE_REPLY:
-        /* XXX */
+        ofp_print_stats_reply(string, oh);
+        ofp_print_nxst_aggregate_reply(string, oh);
         break;
     }
 }