Merge branch 'mainstream'
[sliver-openvswitch.git] / utilities / ovs-ofctl.c
index 48f0fbf..4d5a84e 100644 (file)
@@ -361,7 +361,7 @@ open_vconn_socket(const char *name, struct vconn **vconnp)
                        vconnp);
     if (error && error != ENOENT) {
         ovs_fatal(0, "%s: failed to open socket (%s)", name,
-                  strerror(error));
+                  ovs_strerror(error));
     }
     free(vconn_name);
 
@@ -412,7 +412,7 @@ open_vconn__(const char *name, enum open_target target,
     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);
@@ -632,7 +632,7 @@ ofctl_dump_tables(int argc OVS_UNUSED, char *argv[])
 
 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;
@@ -670,7 +670,7 @@ fetch_port_by_features(const char *vconn_name,
     }
 
     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;
@@ -685,7 +685,7 @@ exit:
 
 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;
@@ -729,8 +729,8 @@ fetch_port_by_stats(const char *vconn_name,
             }
 
             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;
                 }
@@ -746,6 +746,16 @@ fetch_port_by_stats(const char *vconn_name,
     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
@@ -754,13 +764,13 @@ static void
 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
@@ -779,10 +789,10 @@ fetch_ofputil_phy_port(const char *vconn_name, const char *port_name,
 
 /* 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;
@@ -856,8 +866,14 @@ prepare_dump_flows(int argc, char *argv[], bool aggregate,
     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);
@@ -1077,8 +1093,12 @@ ofctl_flow_mod_file(int argc OVS_UNUSED, char *argv[], uint16_t command)
 {
     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);
 }
@@ -1090,7 +1110,12 @@ ofctl_flow_mod(int argc, char *argv[], uint16_t command)
         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);
     }
 }
@@ -1223,7 +1248,7 @@ ofctl_send(struct unixctl_conn *conn, int argc,
         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");
@@ -1260,7 +1285,7 @@ ofctl_barrier(struct unixctl_conn *conn, int argc OVS_UNUSED,
     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;
     }
@@ -1274,7 +1299,7 @@ ofctl_set_output_file(struct unixctl_conn *conn, int argc OVS_UNUSED,
 
     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;
     }
 
@@ -1429,8 +1454,12 @@ ofctl_monitor(int argc, char *argv[])
         } 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);
@@ -1489,7 +1518,7 @@ ofctl_dump_ports(int argc, char *argv[])
 {
     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;
@@ -1528,10 +1557,14 @@ ofctl_packet_out(int argc, char *argv[])
     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]);
@@ -1895,6 +1928,7 @@ static enum ofputil_protocol
 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;
 
@@ -1905,11 +1939,16 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index)
 
     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;
@@ -2040,6 +2079,7 @@ fte_make_flow_mod(const struct fte *fte, int index, uint16_t command,
     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;
@@ -2222,8 +2262,12 @@ static void
 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);
 }
 
@@ -2234,8 +2278,12 @@ ofctl_parse_flows(int argc OVS_UNUSED, char *argv[])
 {
     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);
 }
@@ -2357,7 +2405,7 @@ ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
     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;
@@ -2421,7 +2469,7 @@ ofctl_parse_ofp10_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 
     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;
@@ -2493,7 +2541,7 @@ ofctl_parse_ofp11_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
     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;
@@ -2542,7 +2590,7 @@ ofctl_parse_ofp11_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
     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;
@@ -2600,7 +2648,7 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
     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;
@@ -2627,9 +2675,15 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
         /* Convert to ofpacts. */
         ofpbuf_init(&ofpacts, 0);
         size = of11_in.size;
-        error = ofpacts_pull_openflow11_instructions(
-            &of11_in, of11_in.size, table_id ? atoi(table_id) : 0,
-            &ofpacts);
+        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);
@@ -2683,6 +2737,7 @@ ofctl_check_vlan(int argc OVS_UNUSED, char *argv[])
     struct match of11_match;
 
     enum ofperr error;
+    char *error_s;
 
     match_init_catchall(&match);
     match.flow.vlan_tci = htons(strtoul(argv[1], NULL, 16));
@@ -2692,7 +2747,10 @@ ofctl_check_vlan(int argc OVS_UNUSED, char *argv[])
     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));
@@ -2776,13 +2834,16 @@ ofctl_print_error(int argc OVS_UNUSED, char *argv[])
 
     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));
     }
 }