Delete OFPST_SWITCH and make it available as a Nicira vendor extension.
[sliver-openvswitch.git] / utilities / dpctl.c
index 62c93c6..33a51f8 100644 (file)
@@ -54,6 +54,7 @@
 #include "command-line.h"
 #include "compiler.h"
 #include "dpif.h"
+#include "nicira-ext.h"
 #include "ofp-print.h"
 #include "openflow.h"
 #include "packets.h"
@@ -189,7 +190,6 @@ usage(void)
            "  deldp nl:DP_ID              delete local datapath DP_ID\n"
            "  addif nl:DP_ID IFACE...     add each IFACE as a port on DP_ID\n"
            "  delif nl:DP_ID IFACE...     delete each IFACE from DP_ID\n"
-           "  monitor nl:DP_ID            print packets received\n"
 #endif
            "\nFor local datapaths and remote switches:\n"
            "  show SWITCH                 show basic information\n"
@@ -205,6 +205,7 @@ usage(void)
            "  add-flow SWITCH FLOW        add flow described by FLOW\n"
            "  add-flows SWITCH FILE       add flows from FILE\n"
            "  del-flows SWITCH FLOW       delete matching FLOWs\n"
+           "  monitor SWITCH              print packets received from SWITCH\n"
            "\nFor local datapaths, remote switches, and controllers:\n"
            "  probe VCONN                 probe whether VCONN is up\n"
            "  ping VCONN [N]              latency of N-byte echos\n"
@@ -323,18 +324,6 @@ static void do_del_port(int argc UNUSED, char *argv[])
 {
     add_del_ports(argc, argv, dpif_del_port, "remove", "from");
 }
-
-static void do_monitor(int argc UNUSED, char *argv[])
-{
-    struct dpif dp;
-    open_nl_vconn(argv[1], true, &dp);
-    for (;;) {
-        struct buffer *b;
-        run(dpif_recv_openflow(&dp, &b, true), "dpif_recv_openflow");
-        ofp_print(stderr, b->data, b->size, 2);
-        buffer_delete(b);
-    }
-}
 #endif /* HAVE_NETLINK */
 \f
 /* Generic commands. */
@@ -427,12 +416,32 @@ do_show(int argc UNUSED, char *argv[])
 static void
 do_status(int argc, char *argv[])
 {
-    struct buffer *request;
-    alloc_stats_request(0, OFPST_SWITCH, &request);
+    struct nicira_header *request, *reply;
+    struct vconn *vconn;
+    struct buffer *b;
+
+    request = make_openflow(sizeof *request, OFPT_VENDOR, &b);
+    request->vendor_id = htonl(NX_VENDOR_ID);
+    request->subtype = htonl(NXT_STATUS_REQUEST);
     if (argc > 2) {
-        buffer_put(request, argv[2], strlen(argv[2]));
+        buffer_put(b, argv[2], strlen(argv[2]));
     }
-    dump_stats_transaction(argv[1], request);
+    run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]);
+    run(vconn_transact(vconn, b, &b), "talking to %s", argv[1]);
+    vconn_close(vconn);
+
+    if (b->size < sizeof *reply) {
+        fatal(0, "short reply (%zu bytes)", b->size);
+    }
+    reply = b->data;
+    if (reply->header.type != OFPT_VENDOR
+        || reply->vendor_id != ntohl(NX_VENDOR_ID)
+        || reply->subtype != ntohl(NXT_STATUS_REPLY)) {
+        ofp_print(stderr, b->data, b->size, 2);
+        fatal(0, "bad reply");
+    }
+
+    fwrite(reply + 1, b->size, 1, stdout);
 }
 
 static void
@@ -887,6 +896,29 @@ static void do_del_flows(int argc, char *argv[])
     vconn_close(vconn);
 }
 
+static void
+do_monitor(int argc UNUSED, char *argv[])
+{
+    struct vconn *vconn;
+    const char *name;
+
+    /* If the user specified, e.g., "nl:0", append ":1" to it to ensure that
+     * the connection will subscribe to listen for asynchronous messages, such
+     * as packet-in messages. */
+    if (!strncmp(argv[1], "nl:", 3) && strrchr(argv[1], ':') == &argv[1][2]) {
+        name = xasprintf("%s:1", argv[1]);
+    } else {
+        name = argv[1];
+    }
+    run(vconn_open_block(argv[1], &vconn), "connecting to %s", name);
+    for (;;) {
+        struct buffer *b;
+        run(vconn_recv_block(vconn, &b), "vconn_recv");
+        ofp_print(stderr, b->data, b->size, 2);
+        buffer_delete(b);
+    }
+}
+
 static void
 do_dump_ports(int argc, char *argv[])
 {