I intend to use this in upcoming unit tests. Signed-off-by: Ben Pfaff <b...@nicira.com> --- 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 dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev