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},
vconnp);
if (error && error != ENOENT) {
ovs_fatal(0, "%s: failed to open socket (%s)", name,
- strerror(error));
+ ovs_strerror(error));
}
free(vconn_name);
error = vconn_connect_block(*vconnp);
if (error) {
ovs_fatal(0, "%s: failed to connect to socket (%s)", name,
- strerror(error));
+ ovs_strerror(error));
}
ofp_version = vconn_get_version(*vconnp);
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
static bool
fetch_port_by_features(const char *vconn_name,
- const char *port_name, unsigned int port_no,
+ const char *port_name, ofp_port_t port_no,
struct ofputil_phy_port *pp, bool *trunc)
{
struct ofputil_switch_features features;
}
while (!ofputil_pull_phy_port(oh->version, &b, pp)) {
- if (port_no != UINT_MAX
+ if (port_no != OFPP_NONE
? port_no == pp->port_no
: !strcmp(pp->name, port_name)) {
found = true;
static bool
fetch_port_by_stats(const char *vconn_name,
- const char *port_name, unsigned int port_no,
+ const char *port_name, ofp_port_t port_no,
struct ofputil_phy_port *pp)
{
struct ofpbuf *request;
}
while (!ofputil_pull_phy_port(oh->version, &b, pp)) {
- if (port_no != UINT_MAX ? port_no == pp->port_no
- : !strcmp(pp->name, port_name)) {
+ if (port_no != OFPP_NONE ? port_no == pp->port_no
+ : !strcmp(pp->name, port_name)) {
found = true;
break;
}
return found;
}
+static bool
+str_to_ofp(const char *s, ofp_port_t *ofp_port)
+{
+ bool ret;
+ uint32_t port_;
+
+ ret = str_to_uint(s, 10, &port_);
+ *ofp_port = u16_to_ofp(port_);
+ return ret;
+}
/* Opens a connection to 'vconn_name', fetches the port structure for
* 'port_name' (which may be a port name or number), and copies it into
fetch_ofputil_phy_port(const char *vconn_name, const char *port_name,
struct ofputil_phy_port *pp)
{
- unsigned int port_no;
+ ofp_port_t port_no;
bool found;
bool trunc;
/* Try to interpret the argument as a port number. */
- if (!str_to_uint(port_name, 10, &port_no)) {
- port_no = UINT_MAX;
+ if (!str_to_ofp(port_name, &port_no)) {
+ port_no = OFPP_NONE;
}
/* Try to find the port based on the Features Reply. If it looks
/* Returns the port number corresponding to 'port_name' (which may be a port
* name or number) within the switch 'vconn_name'. */
-static uint16_t
+static ofp_port_t
str_to_port_no(const char *vconn_name, const char *port_name)
{
- uint16_t port_no;
+ ofp_port_t port_no;
if (ofputil_port_from_string(port_name, &port_no)) {
return port_no;
enum ofputil_protocol usable_protocols, protocol;
struct ofputil_flow_stats_request fsr;
struct vconn *vconn;
+ char *error;
+
+ error = parse_ofp_flow_stats_request_str(&fsr, aggregate,
+ argc > 2 ? argv[2] : "");
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
- parse_ofp_flow_stats_request_str(&fsr, aggregate, argc > 2 ? argv[2] : "");
usable_protocols = ofputil_flow_stats_request_usable_protocols(&fsr);
protocol = open_vconn(argv[1], &vconn);
{
struct ofputil_flow_mod *fms = NULL;
size_t n_fms = 0;
+ char *error;
- parse_ofp_flow_mod_file(argv[2], command, &fms, &n_fms);
+ error = parse_ofp_flow_mod_file(argv[2], command, &fms, &n_fms);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
ofctl_flow_mod__(argv[1], fms, n_fms);
free(fms);
}
ofctl_flow_mod_file(argc, argv, command);
} else {
struct ofputil_flow_mod fm;
- parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", command, false);
+ char *error;
+
+ error = parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", command);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
ofctl_flow_mod__(argv[1], &fm, 1);
}
}
error = vconn_send_block(vconn, msg);
if (error) {
ofpbuf_delete(msg);
- ds_put_format(&reply, "%s\n", strerror(error));
+ ds_put_format(&reply, "%s\n", ovs_strerror(error));
ok = false;
} else {
ds_put_cstr(&reply, "sent\n");
error = vconn_send_block(aux->vconn, msg);
if (error) {
ofpbuf_delete(msg);
- unixctl_command_reply_error(conn, strerror(error));
+ unixctl_command_reply_error(conn, ovs_strerror(error));
} else {
aux->conn = conn;
}
fd = open(argv[1], O_CREAT | O_TRUNC | O_WRONLY, 0666);
if (fd < 0) {
- unixctl_command_reply_error(conn, strerror(errno));
+ unixctl_command_reply_error(conn, ovs_strerror(errno));
return;
}
}
}
+/* 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();
- struct tm tm;
- char s[32];
-
- strftime(s, sizeof s, "%Y-%m-%d %H:%M:%S: ",
- gmtime_r(&now, &tm));
+ 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) {
} else if (!strncmp(arg, "watch:", 6)) {
struct ofputil_flow_monitor_request fmr;
struct ofpbuf *msg;
+ char *error;
- parse_flow_monitor_request(&fmr, arg + 6);
+ error = parse_flow_monitor_request(&fmr, arg + 6);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
msg = ofpbuf_new(0);
ofputil_append_flow_monitor_request(&fmr, msg);
}
}
- monitor_vconn(vconn);
+ monitor_vconn(vconn, true);
}
static void
struct vconn *vconn;
open_vconn__(argv[1], SNOOP, &vconn);
- monitor_vconn(vconn);
+ monitor_vconn(vconn, false);
}
static void
{
struct ofpbuf *request;
struct vconn *vconn;
- uint16_t port;
+ ofp_port_t port;
open_vconn(argv[1], &vconn);
port = argc > 2 ? str_to_port_no(argv[1], argv[2]) : OFPP_ANY;
struct ofputil_packet_out po;
struct ofpbuf ofpacts;
struct vconn *vconn;
+ char *error;
int i;
ofpbuf_init(&ofpacts, 64);
- parse_ofpacts(argv[3], &ofpacts);
+ error = parse_ofpacts(argv[3], &ofpacts);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
po.buffer_id = UINT32_MAX;
po.in_port = str_to_port_no(argv[1], argv[2]);
read_flows_from_file(const char *filename, struct classifier *cls, int index)
{
enum ofputil_protocol usable_protocols;
+ int line_number;
struct ds s;
FILE *file;
ds_init(&s);
usable_protocols = OFPUTIL_P_ANY;
- while (!ds_get_preprocessed_line(&s, file)) {
+ line_number = 0;
+ while (!ds_get_preprocessed_line(&s, file, &line_number)) {
struct fte_version *version;
struct ofputil_flow_mod fm;
+ char *error;
- parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), true);
+ error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s));
+ if (error) {
+ ovs_fatal(0, "%s:%d: %s", filename, line_number, error);
+ }
version = xmalloc(sizeof *version);
version->cookie = fm.new_cookie;
fm.cookie = htonll(0);
fm.cookie_mask = htonll(0);
fm.new_cookie = version->cookie;
+ fm.modify_cookie = true;
fm.table_id = 0xff;
fm.command = command;
fm.idle_timeout = version->idle_timeout;
ofctl_parse_flow(int argc OVS_UNUSED, char *argv[])
{
struct ofputil_flow_mod fm;
+ char *error;
- parse_ofp_flow_mod_str(&fm, argv[1], OFPFC_ADD, false);
+ error = parse_ofp_flow_mod_str(&fm, argv[1], OFPFC_ADD);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
ofctl_parse_flows__(&fm, 1);
}
{
struct ofputil_flow_mod *fms = NULL;
size_t n_fms = 0;
+ char *error;
- parse_ofp_flow_mod_file(argv[1], OFPFC_ADD, &fms, &n_fms);
+ error = parse_ofp_flow_mod_file(argv[1], OFPFC_ADD, &fms, &n_fms);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
ofctl_parse_flows__(fms, n_fms);
free(fms);
}
struct ds in;
ds_init(&in);
- while (!ds_get_preprocessed_line(&in, stdin)) {
+ while (!ds_get_preprocessed_line(&in, stdin, NULL)) {
struct ofpbuf of10_out;
struct ofpbuf of10_in;
struct ofpbuf ofpacts;
ds_init(&in);
ds_init(&expout);
- while (!ds_get_preprocessed_line(&in, stdin)) {
+ while (!ds_get_preprocessed_line(&in, stdin, NULL)) {
struct ofpbuf match_in, match_expout;
struct ofp10_match match_out;
struct ofp10_match match_normal;
struct ds in;
ds_init(&in);
- while (!ds_get_preprocessed_line(&in, stdin)) {
+ while (!ds_get_preprocessed_line(&in, stdin, NULL)) {
struct ofpbuf match_in;
struct ofp11_match match_out;
struct match match;
struct ds in;
ds_init(&in);
- while (!ds_get_preprocessed_line(&in, stdin)) {
+ while (!ds_get_preprocessed_line(&in, stdin, NULL)) {
struct ofpbuf of11_out;
struct ofpbuf of11_in;
struct ofpbuf ofpacts;
struct ds in;
ds_init(&in);
- while (!ds_get_preprocessed_line(&in, stdin)) {
+ while (!ds_get_preprocessed_line(&in, stdin, NULL)) {
struct ofpbuf of11_out;
struct ofpbuf of11_in;
struct ofpbuf ofpacts;
enum ofperr error;
size_t size;
struct ds s;
+ const char *table_id;
+ char *instructions;
+
+ /* Parse table_id separated with the follow-up instructions by ",", if
+ * any. */
+ instructions = ds_cstr(&in);
+ table_id = NULL;
+ if (strstr(instructions, ",")) {
+ table_id = strsep(&instructions, ",");
+ }
/* Parse hex bytes. */
ofpbuf_init(&of11_in, 0);
- if (ofpbuf_put_hex(&of11_in, ds_cstr(&in), NULL)[0] != '\0') {
+ if (ofpbuf_put_hex(&of11_in, instructions, NULL)[0] != '\0') {
ovs_fatal(0, "Trailing garbage in hex data");
}
size = of11_in.size;
error = ofpacts_pull_openflow11_instructions(&of11_in, of11_in.size,
&ofpacts);
+ if (!error) {
+ /* Verify actions. */
+ struct flow flow;
+ memset(&flow, 0, sizeof flow);
+ error = ofpacts_check(ofpacts.data, ofpacts.size, &flow, OFPP_MAX,
+ table_id ? atoi(table_id) : 0);
+ }
if (error) {
printf("bad OF1.1 instructions: %s\n\n", ofperr_get_name(error));
ofpbuf_uninit(&ofpacts);
struct match of11_match;
enum ofperr error;
+ char *error_s;
match_init_catchall(&match);
match.flow.vlan_tci = htons(strtoul(argv[1], NULL, 16));
string_s = match_to_string(&match, OFP_DEFAULT_PRIORITY);
printf("%s -> ", string_s);
fflush(stdout);
- parse_ofp_str(&fm, -1, string_s, false);
+ error_s = parse_ofp_str(&fm, -1, string_s);
+ if (error_s) {
+ ovs_fatal(0, "%s", error_s);
+ }
printf("%04"PRIx16"/%04"PRIx16"\n",
ntohs(fm.match.flow.vlan_tci),
ntohs(fm.match.wc.masks.vlan_tci));
for (version = 0; version <= UINT8_MAX; version++) {
const char *name = ofperr_domain_get_name(version);
- if (!name) {
- continue;
+ if (name) {
+ int vendor = ofperr_get_vendor(error, version);
+ int type = ofperr_get_type(error, version);
+ int code = ofperr_get_code(error, version);
+
+ if (vendor != -1 || type != -1 || code != -1) {
+ printf("%s: vendor %#x, type %d, code %d\n",
+ name, vendor, type, code);
+ }
}
- printf("%s: %d,%d\n",
- ofperr_domain_get_name(version),
- ofperr_get_type(error, version),
- ofperr_get_code(error, version));
}
}