classifier: Delete dead code specialized for the exact table.
[openvswitch] / utilities / ovs-ofctl.c
index 13f583e7e3a1bbb064cb4bac1e03d37115370642..1901e242a2369c47fb4c59744a99d7487c50159b 100644 (file)
 #include <sys/stat.h>
 #include <sys/time.h>
 
+#include "byte-order.h"
+#include "classifier.h"
 #include "command-line.h"
 #include "compiler.h"
 #include "dirs.h"
 #include "dpif.h"
+#include "dynamic-string.h"
 #include "netlink.h"
+#include "nx-match.h"
 #include "odp-util.h"
 #include "ofp-parse.h"
 #include "ofp-print.h"
@@ -44,9 +48,8 @@
 #include "util.h"
 #include "vconn.h"
 #include "vlog.h"
-#include "xtoxll.h"
 
-VLOG_DEFINE_THIS_MODULE(ofctl)
+VLOG_DEFINE_THIS_MODULE(ofctl);
 
 
 #define MOD_PORT_CMD_UP      "up"
@@ -354,9 +357,7 @@ do_status(int argc, char *argv[])
     struct vconn *vconn;
     struct ofpbuf *b;
 
-    request = make_openflow(sizeof *request, OFPT_VENDOR, &b);
-    request->vendor = htonl(NX_VENDOR_ID);
-    request->subtype = htonl(NXT_STATUS_REQUEST);
+    request = make_nxmsg(sizeof *request, NXT_STATUS_REQUEST, &b);
     if (argc > 2) {
         ofpbuf_put(b, argv[2], strlen(argv[2]));
         update_openflow_length(b);
@@ -437,14 +438,15 @@ static void
 do_dump_flows(int argc, char *argv[])
 {
     struct ofp_flow_stats_request *req;
-    uint16_t out_port;
+    struct parsed_flow pf;
     struct ofpbuf *request;
 
     req = alloc_stats_request(sizeof *req, OFPST_FLOW, &request);
-    parse_ofp_str(argc > 2 ? argv[2] : "", &req->match, NULL,
-                  &req->table_id, &out_port, NULL, NULL, NULL, NULL);
+    parse_ofp_str(&pf, NULL, argc > 2 ? argv[2] : "");
+    flow_to_match(&pf.rule.flow, pf.rule.wc.wildcards, NXFF_OPENFLOW10,
+                  &req->match);
     memset(&req->pad, 0, sizeof req->pad);
-    req->out_port = htons(out_port);
+    req->out_port = htons(pf.out_port);
 
     dump_stats_transaction(argv[1], request);
 }
@@ -454,13 +456,14 @@ do_dump_aggregate(int argc, char *argv[])
 {
     struct ofp_aggregate_stats_request *req;
     struct ofpbuf *request;
-    uint16_t out_port;
+    struct parsed_flow pf;
 
     req = alloc_stats_request(sizeof *req, OFPST_AGGREGATE, &request);
-    parse_ofp_str(argc > 2 ? argv[2] : "", &req->match, NULL,
-                  &req->table_id, &out_port, NULL, NULL, NULL, NULL);
+    parse_ofp_str(&pf, NULL, argc > 2 ? argv[2] : "");
+    flow_to_match(&pf.rule.flow, pf.rule.wc.wildcards, NXFF_OPENFLOW10,
+                  &req->match);
     memset(&req->pad, 0, sizeof req->pad);
-    req->out_port = htons(out_port);
+    req->out_port = htons(pf.out_port);
 
     dump_stats_transaction(argv[1], request);
 }
@@ -494,26 +497,8 @@ do_add_flow(int argc OVS_UNUSED, char *argv[])
 {
     struct vconn *vconn;
     struct ofpbuf *buffer;
-    struct ofp_flow_mod *ofm;
-    uint16_t priority, idle_timeout, hard_timeout;
-    uint64_t cookie;
-    struct ofp_match match;
-
-    /* Parse and send.  parse_ofp_str() will expand and reallocate the
-     * data in 'buffer', so we can't keep pointers to across the
-     * parse_ofp_str() call. */
-    make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
-    parse_ofp_str(argv[2], &match, buffer,
-                  NULL, NULL, &priority, &idle_timeout, &hard_timeout,
-                  &cookie);
-    ofm = buffer->data;
-    ofm->match = match;
-    ofm->command = htons(OFPFC_ADD);
-    ofm->cookie = htonll(cookie);
-    ofm->idle_timeout = htons(idle_timeout);
-    ofm->hard_timeout = htons(hard_timeout);
-    ofm->buffer_id = htonl(UINT32_MAX);
-    ofm->priority = htons(priority);
+
+    buffer = parse_ofp_flow_mod_str(argv[2], OFPFC_ADD);
 
     open_vconn(argv[1], &vconn);
     send_openflow_buffer(vconn, buffer);
@@ -543,33 +528,12 @@ do_add_flows(int argc OVS_UNUSED, char *argv[])
 static void
 do_mod_flows(int argc OVS_UNUSED, char *argv[])
 {
-    uint16_t priority, idle_timeout, hard_timeout;
-    uint64_t cookie;
     struct vconn *vconn;
     struct ofpbuf *buffer;
-    struct ofp_flow_mod *ofm;
-    struct ofp_match match;
-
-    /* Parse and send.  parse_ofp_str() will expand and reallocate the
-     * data in 'buffer', so we can't keep pointers to across the
-     * parse_ofp_str() call. */
-    make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
-    parse_ofp_str(argv[2], &match, buffer,
-                  NULL, NULL, &priority, &idle_timeout, &hard_timeout,
-                  &cookie);
-    ofm = buffer->data;
-    ofm->match = match;
-    if (strict) {
-        ofm->command = htons(OFPFC_MODIFY_STRICT);
-    } else {
-        ofm->command = htons(OFPFC_MODIFY);
-    }
-    ofm->idle_timeout = htons(idle_timeout);
-    ofm->hard_timeout = htons(hard_timeout);
-    ofm->cookie = htonll(cookie);
-    ofm->buffer_id = htonl(UINT32_MAX);
-    ofm->priority = htons(priority);
+    uint16_t command;
 
+    command = strict ? OFPFC_MODIFY_STRICT : OFPFC_MODIFY;
+    buffer = parse_ofp_flow_mod_str(argv[2], command);
     open_vconn(argv[1], &vconn);
     send_openflow_buffer(vconn, buffer);
     vconn_close(vconn);
@@ -578,25 +542,11 @@ do_mod_flows(int argc OVS_UNUSED, char *argv[])
 static void do_del_flows(int argc, char *argv[])
 {
     struct vconn *vconn;
-    uint16_t priority;
-    uint16_t out_port;
     struct ofpbuf *buffer;
-    struct ofp_flow_mod *ofm;
-
-    /* Parse and send. */
-    ofm = make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
-    parse_ofp_str(argc > 2 ? argv[2] : "", &ofm->match, NULL, NULL,
-                  &out_port, &priority, NULL, NULL, NULL);
-    if (strict) {
-        ofm->command = htons(OFPFC_DELETE_STRICT);
-    } else {
-        ofm->command = htons(OFPFC_DELETE);
-    }
-    ofm->idle_timeout = htons(0);
-    ofm->hard_timeout = htons(0);
-    ofm->buffer_id = htonl(UINT32_MAX);
-    ofm->out_port = htons(out_port);
-    ofm->priority = htons(priority);
+    uint16_t command;
+
+    command = strict ? OFPFC_DELETE_STRICT : OFPFC_DELETE;
+    buffer = parse_ofp_flow_mod_str(argc > 2 ? argv[2] : "", command);
 
     open_vconn(argv[1], &vconn);
     send_openflow_buffer(vconn, buffer);
@@ -610,10 +560,8 @@ do_tun_cookie(int argc OVS_UNUSED, char *argv[])
     struct ofpbuf *buffer;
     struct vconn *vconn;
 
-    tun_id_cookie = make_openflow(sizeof *tun_id_cookie, OFPT_VENDOR, &buffer);
-
-    tun_id_cookie->vendor = htonl(NX_VENDOR_ID);
-    tun_id_cookie->subtype = htonl(NXT_TUN_ID_FROM_COOKIE);
+    tun_id_cookie = make_nxmsg(sizeof *tun_id_cookie, NXT_TUN_ID_FROM_COOKIE,
+                               &buffer);
     tun_id_cookie->set = !strcmp(argv[2], "true");
 
     open_vconn(argv[1], &vconn);
@@ -859,8 +807,14 @@ do_benchmark(int argc OVS_UNUSED, char *argv[])
            count * message_size / (duration / 1000.0));
 }
 
-/* This command is really only useful for testing the flow parser (ofp_parse),
- * so it is undocumented. */
+static void
+do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+{
+    usage();
+}
+\f
+/* Undocumented commands for unit testing. */
+
 static void
 do_parse_flows(int argc OVS_UNUSED, char *argv[])
 {
@@ -880,9 +834,57 @@ do_parse_flows(int argc OVS_UNUSED, char *argv[])
 }
 
 static void
-do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
-{
-    usage();
+do_parse_nx_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+{
+    struct ds in;
+
+    ds_init(&in);
+    while (!ds_get_line(&in, stdin)) {
+        struct ofpbuf nx_match;
+        struct cls_rule rule;
+        int match_len;
+        int error;
+        char *s;
+
+        /* Delete comments, skip blank lines. */
+        s = ds_cstr(&in);
+        if (*s == '#') {
+            puts(s);
+            continue;
+        }
+        if (strchr(s, '#')) {
+            *strchr(s, '#') = '\0';
+        }
+        if (s[strspn(s, " ")] == '\0') {
+            putchar('\n');
+            continue;
+        }
+
+        /* Convert string to nx_match. */
+        ofpbuf_init(&nx_match, 0);
+        match_len = nx_match_from_string(ds_cstr(&in), &nx_match);
+
+        /* Convert nx_match to cls_rule. */
+        error = nx_pull_match(&nx_match, match_len, 0, &rule);
+        if (!error) {
+            char *out;
+
+            /* Convert cls_rule back to nx_match. */
+            ofpbuf_uninit(&nx_match);
+            ofpbuf_init(&nx_match, 0);
+            match_len = nx_put_match(&nx_match, &rule);
+
+            /* Convert nx_match to string. */
+            out = nx_match_to_string(nx_match.data, match_len);
+            puts(out);
+            free(out);
+        } else {
+            printf("nx_pull_match() returned error %x\n", error);
+        }
+
+        ofpbuf_uninit(&nx_match);
+    }
+    ds_destroy(&in);
 }
 
 static const struct command all_commands[] = {
@@ -905,7 +907,11 @@ static const struct command all_commands[] = {
     { "probe", 1, 1, do_probe },
     { "ping", 1, 2, do_ping },
     { "benchmark", 3, 3, do_benchmark },
-    { "parse-flows", 1, 1, do_parse_flows },
     { "help", 0, INT_MAX, do_help },
+
+    /* Undocumented commands for testing. */
+    { "parse-flows", 1, 1, do_parse_flows },
+    { "parse-nx-match", 0, 0, do_parse_nx_match },
+
     { NULL, 0, 0, NULL },
 };