+ dump_trivial_stats_transaction(argv[1], OFPST_PORT);
+}
+
+static void
+do_probe(int argc, char *argv[])
+{
+ struct buffer *request;
+ struct vconn *vconn;
+ struct buffer *reply;
+
+ make_openflow(sizeof(struct ofp_header), OFPT_ECHO_REQUEST, &request);
+ run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]);
+ run(vconn_transact(vconn, request, &reply), "talking to %s", argv[1]);
+ if (reply->size != request->size) {
+ fatal(0, "reply does not match request");
+ }
+ buffer_delete(reply);
+ vconn_close(vconn);
+}
+
+static void
+do_ping(int argc, char *argv[])
+{
+ size_t max_payload = 65535 - sizeof(struct ofp_header);
+ unsigned int payload;
+ struct vconn *vconn;
+ int i;
+
+ payload = argc > 2 ? atoi(argv[2]) : 64;
+ if (payload > max_payload) {
+ fatal(0, "payload must be between 0 and %zu bytes", max_payload);
+ }
+
+ run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]);
+ for (i = 0; i < 10; i++) {
+ struct timeval start, end;
+ struct buffer *request, *reply;
+ struct ofp_header *rq_hdr, *rpy_hdr;
+
+ rq_hdr = make_openflow(sizeof(struct ofp_header) + payload,
+ OFPT_ECHO_REQUEST, &request);
+ random_bytes(rq_hdr + 1, payload);
+
+ gettimeofday(&start, NULL);
+ run(vconn_transact(vconn, buffer_clone(request), &reply), "transact");
+ gettimeofday(&end, NULL);
+
+ rpy_hdr = reply->data;
+ if (reply->size != request->size
+ || memcmp(rpy_hdr + 1, rq_hdr + 1, payload)
+ || rpy_hdr->xid != rq_hdr->xid
+ || rpy_hdr->type != OFPT_ECHO_REPLY) {
+ printf("Reply does not match request. Request:\n");
+ ofp_print(stdout, request, request->size, 2);
+ printf("Reply:\n");
+ ofp_print(stdout, reply, reply->size, 2);
+ }
+ printf("%d bytes from %s: xid=%08"PRIx32" time=%.1f ms\n",
+ reply->size - sizeof *rpy_hdr, argv[1], rpy_hdr->xid,
+ (1000*(double)(end.tv_sec - start.tv_sec))
+ + (.001*(end.tv_usec - start.tv_usec)));
+ buffer_delete(request);
+ buffer_delete(reply);
+ }
+ vconn_close(vconn);
+}
+
+static void
+do_benchmark(int argc, char *argv[])
+{
+ size_t max_payload = 65535 - sizeof(struct ofp_header);
+ struct timeval start, end;
+ unsigned int payload_size, message_size;
+ struct vconn *vconn;
+ double duration;
+ int count;
+ int i;
+
+ payload_size = atoi(argv[2]);
+ if (payload_size > max_payload) {
+ fatal(0, "payload must be between 0 and %zu bytes", max_payload);
+ }
+ message_size = sizeof(struct ofp_header) + payload_size;
+
+ count = atoi(argv[3]);
+
+ printf("Sending %d packets * %u bytes (with header) = %u bytes total\n",
+ count, message_size, count * message_size);
+
+ run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]);
+ gettimeofday(&start, NULL);
+ for (i = 0; i < count; i++) {
+ struct buffer *request, *reply;
+ struct ofp_header *rq_hdr;
+
+ rq_hdr = make_openflow(message_size, OFPT_ECHO_REQUEST, &request);
+ memset(rq_hdr + 1, 0, payload_size);
+ run(vconn_transact(vconn, request, &reply), "transact");
+ buffer_delete(reply);
+ }
+ gettimeofday(&end, NULL);
+ vconn_close(vconn);
+
+ duration = ((1000*(double)(end.tv_sec - start.tv_sec))
+ + (.001*(end.tv_usec - start.tv_usec)));
+ printf("Finished in %.1f ms (%.0f packets/s) (%.0f bytes/s)\n",
+ duration, count / (duration / 1000.0),
+ count * message_size / (duration / 1000.0));