datapath: Make adding and attaching a vport a single step.
[sliver-openvswitch.git] / lib / ofp-print.c
index 78f3649..eb7e534 100644 (file)
 #include <stdlib.h>
 #include <ctype.h>
 
+#include "byte-order.h"
 #include "compiler.h"
 #include "dynamic-string.h"
 #include "flow.h"
+#include "ofp-util.h"
 #include "ofpbuf.h"
 #include "openflow/openflow.h"
 #include "openflow/nicira-ext.h"
 #include "packets.h"
 #include "pcap.h"
 #include "util.h"
-#include "xtoxll.h"
 
 static void ofp_print_port_name(struct ds *string, uint16_t port);
+static void ofp_print_queue_name(struct ds *string, uint32_t port);
 
 /* Returns a string that represents the contents of the Ethernet frame in the
  * 'len' bytes starting at 'data' to 'stream' as output by tcpdump.
@@ -129,14 +131,13 @@ ofp_packet_in(struct ds *string, const void *oh, size_t len, int verbosity)
     ds_put_char(string, '\n');
 
     if (verbosity > 0) {
-        flow_t flow;
+        struct flow flow;
         struct ofpbuf packet;
-        struct ofp_match match;
+
         packet.data = (void *) op->data;
         packet.size = data_len;
         flow_extract(&packet, 0, ntohs(op->in_port), &flow);
-        flow_to_match(&flow, 0, false, &match);
-        ofp_print_match(string, &match, verbosity);
+        flow_format(string, &flow);
         ds_put_char(string, '\n');
     }
     if (verbosity > 1) {
@@ -182,6 +183,22 @@ static void ofp_print_port_name(struct ds *string, uint16_t port)
     ds_put_cstr(string, name);
 }
 
+static void
+print_note(struct ds *string, const struct nx_action_note *nan)
+{
+    size_t len;
+    size_t i;
+
+    ds_put_cstr(string, "note:");
+    len = ntohs(nan->len) - offsetof(struct nx_action_note, note);
+    for (i = 0; i < len; i++) {
+        if (i) {
+            ds_put_char(string, '.');
+        }
+        ds_put_format(string, "%02"PRIx8, nan->note[i]);
+    }
+}
+
 static void
 ofp_print_nx_action(struct ds *string, const struct nx_action_header *nah)
 {
@@ -196,7 +213,7 @@ ofp_print_nx_action(struct ds *string, const struct nx_action_header *nah)
     case NXAST_SET_TUNNEL: {
         const struct nx_action_set_tunnel *nast =
                                             (struct nx_action_set_tunnel *)nah;
-        ds_put_format(string, "set_tunnel:0x%08"PRIx32, ntohl(nast->tun_id));
+        ds_put_format(string, "set_tunnel:%#"PRIx32, ntohl(nast->tun_id));
         break;
     }
 
@@ -204,6 +221,21 @@ ofp_print_nx_action(struct ds *string, const struct nx_action_header *nah)
         ds_put_cstr(string, "drop_spoofed_arp");
         break;
 
+    case NXAST_SET_QUEUE: {
+        const struct nx_action_set_queue *nasq =
+                                            (struct nx_action_set_queue *)nah;
+        ds_put_format(string, "set_queue:%u", ntohl(nasq->queue_id));
+        break;
+    }
+
+    case NXAST_POP_QUEUE:
+        ds_put_cstr(string, "pop_queue");
+        break;
+
+    case NXAST_NOTE:
+        print_note(string, (const struct nx_action_note *) nah);
+        break;
+
     default:
         ds_put_format(string, "***unknown Nicira action:%d***",
                       ntohs(nah->subtype));
@@ -282,10 +314,15 @@ ofp_print_action(struct ds *string, const struct ofp_action_header *ah,
         return -1;
     }
 
-    if ((len % 8) != 0) {
+    if (!len) {
+        ds_put_format(string, "***zero-length action***\n");
+        return 8;
+    }
+
+    if ((len % OFP_ACTION_ALIGN) != 0) {
         ds_put_format(string,
-                "***action %"PRIu16" length not a multiple of 8***\n",
-                type);
+                      "***action %"PRIu16" length not a multiple of %d***\n",
+                      type, OFP_ACTION_ALIGN);
         return -1;
     }
 
@@ -533,7 +570,7 @@ static void ofp_print_port_features(struct ds *string, uint32_t features)
 static void
 ofp_print_phy_port(struct ds *string, const struct ofp_phy_port *port)
 {
-    uint8_t name[OFP_MAX_PORT_NAME_LEN];
+    char name[OFP_MAX_PORT_NAME_LEN];
     int j;
 
     memcpy(name, port->name, sizeof name);
@@ -725,10 +762,10 @@ ofp_match_to_string(const struct ofp_match *om, int verbosity)
         } else {
             print_wild(&f, "nw_proto=", w & OFPFW_NW_PROTO, verbosity,
                        "%u", om->nw_proto);
-            print_wild(&f, "nw_tos=", w & OFPFW_NW_TOS, verbosity,
-                       "%u", om->nw_tos);
         }
     }
+    print_wild(&f, "nw_tos=", w & OFPFW_NW_TOS, verbosity,
+               "%u", om->nw_tos);
     if (om->nw_proto == IP_TYPE_ICMP) {
         print_wild(&f, "icmp_type=", w & OFPFW_ICMP_TYPE, verbosity,
                    "%d", ntohs(om->icmp_type));
@@ -751,31 +788,50 @@ ofp_print_flow_mod(struct ds *string, const void *oh, size_t len,
 {
     const struct ofp_flow_mod *ofm = oh;
 
+    ds_put_char(string, ' ');
     ofp_print_match(string, &ofm->match, verbosity);
+    if (ds_last(string) != ' ') {
+        ds_put_char(string, ' ');
+    }
+
     switch (ntohs(ofm->command)) {
     case OFPFC_ADD:
-        ds_put_cstr(string, " ADD: ");
+        ds_put_cstr(string, "ADD:");
         break;
     case OFPFC_MODIFY:
-        ds_put_cstr(string, " MOD: ");
+        ds_put_cstr(string, "MOD:");
         break;
     case OFPFC_MODIFY_STRICT:
-        ds_put_cstr(string, " MOD_STRICT: ");
+        ds_put_cstr(string, "MOD_STRICT:");
         break;
     case OFPFC_DELETE:
-        ds_put_cstr(string, " DEL: ");
+        ds_put_cstr(string, "DEL:");
         break;
     case OFPFC_DELETE_STRICT:
-        ds_put_cstr(string, " DEL_STRICT: ");
+        ds_put_cstr(string, "DEL_STRICT:");
         break;
     default:
-        ds_put_format(string, " cmd:%d ", ntohs(ofm->command));
+        ds_put_format(string, "cmd:%d", ntohs(ofm->command));
     }
-    ds_put_format(string, "cookie:0x%"PRIx64" idle:%d hard:%d pri:%d "
-            "buf:%#x flags:%"PRIx16" ", ntohll(ofm->cookie),
-            ntohs(ofm->idle_timeout), ntohs(ofm->hard_timeout),
-            ofm->match.wildcards ? ntohs(ofm->priority) : (uint16_t)-1,
-            ntohl(ofm->buffer_id), ntohs(ofm->flags));
+    if (ofm->cookie != htonll(0)) {
+        ds_put_format(string, " cookie:0x%"PRIx64, ntohll(ofm->cookie));
+    }
+    if (ofm->idle_timeout != htons(OFP_FLOW_PERMANENT)) {
+        ds_put_format(string, " idle:%d", ntohs(ofm->idle_timeout));
+    }
+    if (ofm->hard_timeout != htons(OFP_FLOW_PERMANENT)) {
+        ds_put_format(string, " hard:%d", ntohs(ofm->hard_timeout));
+    }
+    if (ofm->priority != htons(32768)) {
+        ds_put_format(string, " pri:%"PRIu16, ntohs(ofm->priority));
+    }
+    if (ofm->buffer_id != htonl(UINT32_MAX)) {
+        ds_put_format(string, " buf:%#"PRIx32, ntohl(ofm->buffer_id));
+    }
+    if (ofm->flags != htons(0)) {
+        ds_put_format(string, " flags:%"PRIx16, ntohs(ofm->flags));
+    }
+    ds_put_cstr(string, " ");
     ofp_print_actions(string, ofm->actions,
                       len - offsetof(struct ofp_flow_mod, actions));
     ds_put_char(string, '\n');
@@ -805,11 +861,15 @@ ofp_print_flow_removed(struct ds *string, const void *oh,
         ds_put_format(string, "**%"PRIu8"**", ofr->reason);
         break;
     }
-    ds_put_format(string,
-         " cookie0x%"PRIx64" pri%"PRIu16" secs%"PRIu32" nsecs%"PRIu32
+
+    if (ofr->cookie != htonll(0)) {
+        ds_put_format(string, " cookie:0x%"PRIx64, ntohll(ofr->cookie));
+    }
+    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",
-         ntohll(ofr->cookie),
-         ofr->match.wildcards ? ntohs(ofr->priority) : (uint16_t)-1,
          ntohl(ofr->duration_sec), ntohl(ofr->duration_nsec),
          ntohs(ofr->idle_timeout), ntohll(ofr->packet_count),
          ntohll(ofr->byte_count));
@@ -1165,6 +1225,53 @@ ofp_table_stats_reply(struct ds *string, const void *body, size_t len,
      }
 }
 
+static void
+ofp_print_queue_name(struct ds *string, uint32_t queue_id)
+{
+    if (queue_id == OFPQ_ALL) {
+        ds_put_cstr(string, "ALL");
+    } else {
+        ds_put_format(string, "%"PRIu32, queue_id);
+    }
+}
+
+static void
+ofp_queue_stats_request(struct ds *string, const void *body_,
+                       size_t len OVS_UNUSED, int verbosity OVS_UNUSED)
+{
+    const struct ofp_queue_stats_request *qsr = body_;
+
+    ds_put_cstr(string, "port=");
+    ofp_print_port_name(string, ntohs(qsr->port_no));
+
+    ds_put_cstr(string, " queue=");
+    ofp_print_queue_name(string, ntohl(qsr->queue_id));
+}
+
+static void
+ofp_queue_stats_reply(struct ds *string, const void *body, size_t len,
+                     int verbosity)
+{
+    const struct ofp_queue_stats *qs = body;
+    size_t n = len / sizeof *qs;
+    ds_put_format(string, " %zu queues\n", n);
+    if (verbosity < 1) {
+        return;
+    }
+
+    for (; n--; qs++) {
+        ds_put_cstr(string, "  port ");
+        ofp_print_port_name(string, ntohs(qs->port_no));
+        ds_put_cstr(string, " queue ");
+        ofp_print_queue_name(string, ntohl(qs->queue_id));
+        ds_put_cstr(string, ": ");
+
+        print_port_stat(string, "bytes=", ntohll(qs->tx_bytes), 1);
+        print_port_stat(string, "pkts=", ntohll(qs->tx_packets), 1);
+        print_port_stat(string, "errors=", ntohll(qs->tx_errors), 0);
+    }
+}
+
 static void
 vendor_stat(struct ds *string, const void *body, size_t len,
             int verbosity OVS_UNUSED)
@@ -1234,6 +1341,14 @@ print_stats(struct ds *string, int type, const void *body, size_t body_len,
               ofp_port_stats_request },
             { 0, SIZE_MAX, ofp_port_stats_reply },
         },
+        {
+            OFPST_QUEUE,
+            "queue",
+            { sizeof(struct ofp_queue_stats_request),
+              sizeof(struct ofp_queue_stats_request),
+              ofp_queue_stats_request },
+            { 0, SIZE_MAX, ofp_queue_stats_reply },
+        },
         {
             OFPST_VENDOR,
             "vendor-specific",
@@ -1485,7 +1600,7 @@ ofp_to_string(const void *oh_, size_t len, int verbosity)
         }
     }
 
-    ds_put_format(&string, "%s (xid=0x%"PRIx32"):", pkt->name, oh->xid);
+    ds_put_format(&string, "%s (xid=0x%"PRIx32"):", pkt->name, ntohl(oh->xid));
 
     if (ntohs(oh->length) > len)
         ds_put_format(&string, " (***truncated to %zu bytes from %"PRIu16"***)",