I intend to use this in upcoming unit tests.
Signed-off-by: Ben Pfaff <[email protected]>
---
utilities/ovs-ofctl.8.in | 15 +++++++--
utilities/ovs-ofctl.c | 75 +++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index adc895f..415dddc 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1130,11 +1130,18 @@ increase verbosity further.
.so lib/common.man
.
.SH "RUNTIME MANAGEMENT COMMANDS"
-\fBovs\-appctl\fR(8) can send commands to a running \fBovs\-ofctl\fR process.
-The currently supported commands only apply when executing the \fBmonitor\fR or
-\fBsnoop\fR commands and are described below.
+\fBovs\-appctl\fR(8) can send commands to a running \fBovs\-ofctl\fR
+process. The supported commands are listed below.
+.
.IP "\fBexit\fR"
-Causes \fBovs\-ofctl\fR to gracefully terminate.
+Causes \fBovs\-ofctl\fR to gracefully terminate. This command applies
+only when executing the \fBmonitor\fR or \fBsnoop\fR commands.
+.
+.IP "\fBofctl/send \fIofmsg\fR..."
+Sends each \fIofmsg\fR, specified as a sequence of hex digits that
+express an OpenFlow message, on the OpenFlow connection. This command
+is useful only when executing the \fBmonitor\fR command.
+.
.SH EXAMPLES
.
The following examples assume that \fBovs\-vswitchd\fR has a bridge
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 204d340..0006bd6 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -829,6 +829,77 @@ monitor_set_invalid_ttl_to_controller(struct vconn *vconn)
return 0;
}
+/* Converts hex digits in 'hex' to an OpenFlow message in '*ohp'. The
+ * caller must free '*ohp'. On success, returns NULL. On failure, returns
+ * an error message and stores NULL in '*ohp'. */
+static const char *
+openflow_from_hex(const char *hex, struct ofpbuf **msgp)
+{
+ struct ofp_header *oh;
+ struct ofpbuf *msg;
+
+ msg = ofpbuf_new(strlen(hex) / 2);
+ *msgp = NULL;
+
+ if (ofpbuf_put_hex(msg, hex, NULL)[0] != '\0') {
+ ofpbuf_delete(msg);
+ return "Trailing garbage in hex data";
+ }
+
+ if (msg->size < sizeof(struct ofp_header)) {
+ ofpbuf_delete(msg);
+ return "Message too short for OpenFlow";
+ }
+
+ oh = msg->data;
+ if (msg->size != ntohs(oh->length)) {
+ ofpbuf_delete(msg);
+ return "Message size does not match length in OpenFlow header";
+ }
+
+ *msgp = msg;
+ return NULL;
+}
+
+static void
+ofctl_send(struct unixctl_conn *conn, int argc,
+ const char *argv[], void *vconn_)
+{
+ struct vconn *vconn = vconn_;
+ struct ds reply;
+ bool ok;
+ int i;
+
+ ok = true;
+ ds_init(&reply);
+ for (i = 1; i < argc; i++) {
+ const char *error_msg;
+ struct ofpbuf *msg;
+ int error;
+
+ error_msg = openflow_from_hex(argv[i], &msg);
+ if (error_msg) {
+ ds_put_format(&reply, "%s\n", error_msg);
+ ok = false;
+ continue;
+ }
+
+ fprintf(stderr, "send: ");
+ ofp_print(stderr, msg->data, msg->size, verbosity);
+
+ error = vconn_send_block(vconn, msg);
+ if (error) {
+ ofpbuf_delete(msg);
+ ds_put_format(&reply, "%s\n", strerror(error));
+ ok = false;
+ } else {
+ ds_put_cstr(&reply, "sent\n");
+ }
+ }
+ unixctl_command_reply(conn, ok ? 200 : 501, ds_cstr(&reply));
+ ds_destroy(&reply);
+}
+
static void
monitor_vconn(struct vconn *vconn)
{
@@ -864,6 +935,8 @@ monitor_vconn(struct vconn *vconn)
ovs_fatal(error, "failed to create unixctl server");
}
unixctl_command_register("exit", "", 0, 0, ofctl_exit, &exiting);
+ unixctl_command_register("ofctl/send", "OFMSG...", 1, INT_MAX,
+ ofctl_send, vconn);
daemonize_complete();
/* Now get stderr back. */
--
1.7.2.5
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev