OFP_VERSION_OPTION_ENUMS,
VLOG_OPTION_ENUMS
};
- static struct option long_options[] = {
+ static const struct option long_options[] = {
{"timeout", required_argument, NULL, 't'},
{"strict", no_argument, NULL, OPT_STRICT},
{"readd", no_argument, NULL, OPT_READD},
return error;
}
+enum open_target { MGMT, SNOOP };
+
static enum ofputil_protocol
-open_vconn__(const char *name, const char *default_suffix,
+open_vconn__(const char *name, enum open_target target,
struct vconn **vconnp)
{
+ const char *suffix = target == MGMT ? "mgmt" : "snoop";
char *datapath_name, *datapath_type, *socket_name;
enum ofputil_protocol protocol;
char *bridge_path;
int ofp_version;
int error;
- bridge_path = xasprintf("%s/%s.%s", ovs_rundir(), name, default_suffix);
+ bridge_path = xasprintf("%s/%s.%s", ovs_rundir(), name, suffix);
ofproto_parse_name(name, &datapath_name, &datapath_type);
- socket_name = xasprintf("%s/%s.%s",
- ovs_rundir(), datapath_name, default_suffix);
+ socket_name = xasprintf("%s/%s.%s", ovs_rundir(), datapath_name, suffix);
free(datapath_name);
free(datapath_type);
if (strchr(name, ':')) {
- run(vconn_open_block(name, get_allowed_ofp_versions(), DSCP_DEFAULT,
- vconnp),
+ run(vconn_open(name, get_allowed_ofp_versions(), DSCP_DEFAULT, vconnp),
"connecting to %s", name);
} else if (!open_vconn_socket(name, vconnp)) {
/* Fall Through. */
ovs_fatal(0, "%s is not a bridge or a socket", name);
}
+ if (target == SNOOP) {
+ vconn_set_recv_any_version(*vconnp);
+ }
+
free(bridge_path);
free(socket_name);
static enum ofputil_protocol
open_vconn(const char *name, struct vconn **vconnp)
{
- return open_vconn__(name, "mgmt", vconnp);
+ return open_vconn__(name, MGMT, vconnp);
}
static void
vconn_close(vconn);
}
-/* Sends 'request', which should be a request that only has a reply if an error
- * occurs, and waits for it to succeed or fail. If an error does occur, prints
- * it and exits with an error.
+/* Sends all of the 'requests', which should be requests that only have replies
+ * if an error occurs, and waits for them to succeed or fail. If an error does
+ * occur, prints it and exits with an error.
*
* Destroys all of the 'requests'. */
static void
}
}
+/* Prints to stdout all of the messages received on 'vconn'.
+ *
+ * Iff 'reply_to_echo_requests' is true, sends a reply to any echo request
+ * received on 'vconn'. */
static void
-monitor_vconn(struct vconn *vconn)
+monitor_vconn(struct vconn *vconn, bool reply_to_echo_requests)
{
struct barrier_aux barrier_aux = { vconn, NULL };
struct unixctl_server *server;
run(retval, "vconn_recv");
if (timestamp) {
- time_t now = time_wall();
- char s[32];
-
- strftime(s, sizeof s, "%Y-%m-%d %H:%M:%S: ", gmtime(&now));
+ char *s = xastrftime("%Y-%m-%d %H:%M:%S: ", time_wall(), true);
fputs(s, stderr);
+ free(s);
}
ofptype_decode(&type, b->data);
ofp_print(stderr, b->data, b->size, verbosity + 2);
- ofpbuf_delete(b);
- if (barrier_aux.conn && type == OFPTYPE_BARRIER_REPLY) {
- unixctl_command_reply(barrier_aux.conn, NULL);
- barrier_aux.conn = NULL;
+ switch ((int) type) {
+ case OFPTYPE_BARRIER_REPLY:
+ if (barrier_aux.conn) {
+ unixctl_command_reply(barrier_aux.conn, NULL);
+ barrier_aux.conn = NULL;
+ }
+ break;
+
+ case OFPTYPE_ECHO_REQUEST:
+ if (reply_to_echo_requests) {
+ struct ofpbuf *reply;
+
+ reply = make_echo_reply(b->data);
+ retval = vconn_send_block(vconn, reply);
+ if (retval) {
+ ovs_fatal(retval, "failed to send echo reply");
+ }
+ }
+ break;
}
+ ofpbuf_delete(b);
}
if (exiting) {
}
}
- monitor_vconn(vconn);
+ monitor_vconn(vconn, true);
}
static void
{
struct vconn *vconn;
- open_vconn__(argv[1], "snoop", &vconn);
- monitor_vconn(vconn);
+ open_vconn__(argv[1], SNOOP, &vconn);
+ monitor_vconn(vconn, false);
}
static void
break;
}
}
- ovs_assert(IS_POW2(protocol));
+ ovs_assert(is_pow2(protocol));
printf("chosen protocol: %s\n", ofputil_protocol_to_string(protocol));