From: Alex Wang <al...@nicira.com>

Since the use of single datapath, all bridges belonging to the same type of
datapath will use the same (single) datapath. This causes confusion in the
current 'ofproto/trace' command. Especially, when given the unrelated
'bridge' and 'in_port' combination, the current implementation will still
be able to process and give misleading output. Thusly, this patch changes
the 'ofproto/trace' command syntax to formats shown as follow.

ofproto/trace [datapath] priority tun_id in_port mark packet
ofproto/trace [datapath] dp_flow [-generate]
ofproto/trace bridge br_flow [-generate]

Therein, the bridge name is replaced by datapath name in the first format,
since the mapping between in_port and the corresponding datapath is unique.
The second format requires datapath name since it uses 'ovs-dpctl dump-flows'
output. And the thrid format requires bridge name since it uses 'ovs-ofctl
add-flow' input like flow.

Signed-off-by: Alex Wang <al...@nicira.com>
---
 ofproto/ofproto-dpif.c |  176 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 133 insertions(+), 43 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 6ec1c23..6550af3 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -6073,7 +6073,7 @@ fix_sflow_action(struct action_xlate_ctx *ctx)
     }
 
     cookie = ofpbuf_at(ctx->odp_actions, ctx->user_cookie_offset,
-                       sizeof cookie->sflow);
+                       sizeof(*cookie));
     ovs_assert(cookie->type == USER_ACTION_COOKIE_SFLOW);
 
     compose_sflow_cookie(ctx->ofproto, base->vlan_tci,
@@ -8138,7 +8138,9 @@ static void
 ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
                       void *aux OVS_UNUSED)
 {
-    const char *dpname = argv[1];
+    const char **adjusted_argv;
+    const char *dpname;
+    const struct dpif_backer *backer;
     struct ofproto_dpif *ofproto;
     struct ofpbuf odp_key;
     struct ofpbuf *packet;
@@ -8146,59 +8148,108 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int 
argc, const char *argv[],
     struct ds result;
     struct flow flow;
     char *s;
+    bool is_dp;
+    bool has_name;
 
+    is_dp = false;
+    has_name = false;
+    dpname = NULL;
     packet = NULL;
+    backer = NULL;
     ofpbuf_init(&odp_key, 0);
     ds_init(&result);
 
-    ofproto = ofproto_dpif_lookup(dpname);
-    if (!ofproto) {
-        unixctl_command_reply_error(conn, "Unknown ofproto (use ofproto/list "
-                                    "for help)");
-        goto exit;
+    /* Check the existence of datapath name in the argv. */
+    if (argc == 2 || (argc == 3 && !strcmp(argv[2], "-generate"))
+        || argc == 6) {
+        /* Check the number of datapaths. */
+        if (shash_count(&all_dpif_backers) == 1) {
+           is_dp = true;
+            has_name = false;
+        } else {
+            unixctl_command_reply_error(conn, "Must specify datapath name, "
+                                 "there is more than one type of datapath");
+            goto exit;
+        }
+    } else {
+        /* Else, the argv[1] is the datapath or bridge name.
+         * And since there are only three types of datapath (ovs-system,
+         * ovs-netdev and ovs-dummy), exact match is used to distingush
+         * datapath name and bridge name. */
+        if (!strcmp(argv[1], "ovs-system") || !strcmp(argv[1], "ovs-netdev")
+            || !strcmp(argv[1], "ovs-dummy")) {
+            is_dp = true;
+            /* extract the type of datapath */
+            dpname = argv[1] + 4;
+        } else {
+            is_dp = false;
+            dpname = argv[1];
+        }
+        has_name = true;
     }
-    if (argc == 3 || (argc == 4 && !strcmp(argv[3], "-generate"))) {
-        /* ofproto/trace dpname flow [-generate] */
-        const char *flow_s = argv[2];
-        const char *generate_s = argv[3];
 
-        /* Allow 'flow_s' to be either a datapath flow or an OpenFlow-like
-         * flow.  We guess which type it is based on whether 'flow_s' contains
-         * an '(', since a datapath flow always contains '(') but an
-         * OpenFlow-like flow should not (in fact it's allowed but I believe
-         * that's not documented anywhere).
-         *
-         * An alternative would be to try to parse 'flow_s' both ways, but then
-         * it would be tricky giving a sensible error message.  After all, do
-         * you just say "syntax error" or do you present both error messages?
-         * Both choices seem lousy. */
-        if (strchr(flow_s, '(')) {
-            int error;
+    /* If datapath is specified, extract the corresponding backer object. */
+    if (is_dp) {
+        if (has_name) {
+            backer = shash_find_data(&all_dpif_backers, dpname);
+        } else {
+            struct shash_node *node;
+            adjusted_argv = argv;
+            node = shash_first(&all_dpif_backers);
+            backer = node->data;
+        }
+        if (!backer) {
+            unixctl_command_reply_error(conn, "Cannot find datapath "
+                           "of this name");
+            goto exit;
+        }
+    }
+
+    /* Adjust the argv based on the existence of datapath or bridge name. */
+    if (has_name) {
+        adjusted_argv = argv + 2;
+    } else {
+        adjusted_argv = argv + 1;
+    }
+
+    if (argc > 1 && argc < 5) {
+        /* ofproto/trace [dpname] flow [-generate] */
+        const char *flow_s = adjusted_argv[0];
+        const char *generate_s = adjusted_argv[1];
 
+        if (is_dp) {
             /* Convert string to datapath key. */
-            ofpbuf_init(&odp_key, 0);
-            error = odp_flow_key_from_string(flow_s, NULL, &odp_key);
-            if (error) {
-                unixctl_command_reply_error(conn, "Bad flow syntax");
+            if (odp_flow_key_from_string(flow_s, NULL, &odp_key)) {
+                unixctl_command_reply_error(conn, "Bad datapath flow syntax");
                 goto exit;
             }
 
-            /* The user might have specified the wrong ofproto but within the
-             * same backer.  That's OK, ofproto_receive() can find the right
-             * one for us. */
-            if (ofproto_receive(ofproto->backer, NULL, odp_key.data,
+            /* Extract the ofproto_dpif object from the ofproto_receive()
+             * function. */
+            if (ofproto_receive(backer, NULL, odp_key.data,
                                 odp_key.size, &flow, NULL, &ofproto, NULL,
                                 &initial_vals)) {
-                unixctl_command_reply_error(conn, "Invalid flow");
+                unixctl_command_reply_error(conn, "Invalid datapath flow");
                 goto exit;
             }
             ds_put_format(&result, "Bridge: %s\n", ofproto->up.name);
         } else {
+            /* ofproto/trace brname flow [-generate] */
             char *error_s;
 
+            /* Extract the ofproto_dpif object from the
+             * ofproto_dpif_lookup() function. */
+            ofproto = ofproto_dpif_lookup(dpname);
+            if (!ofproto) {
+                unixctl_command_reply_error(conn, "Unknown bridge or "
+                                    "datapath name");
+                goto exit;
+            }
+
             error_s = parse_ofp_exact_flow(&flow, argv[2]);
             if (error_s) {
-                unixctl_command_reply_error(conn, error_s);
+                unixctl_command_reply_error(conn, "Cannot parse the "
+                                    "openflow flow");
                 free(error_s);
                 goto exit;
             }
@@ -8206,24 +8257,61 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int 
argc, const char *argv[],
             initial_vals.vlan_tci = flow.vlan_tci;
             initial_vals.tunnel_ip_tos = flow.tunnel.ip_tos;
         }
-
         /* Generate a packet, if requested. */
         if (generate_s) {
             packet = ofpbuf_new(0);
             flow_compose(packet, &flow);
         }
-    } else if (argc == 7) {
-        /* ofproto/trace dpname priority tun_id in_port mark packet */
-        const char *priority_s = argv[2];
-        const char *tun_id_s = argv[3];
-        const char *in_port_s = argv[4];
-        const char *mark_s = argv[5];
-        const char *packet_s = argv[6];
+    } else if (argc == 6 || argc == 7) {
+        /* ofproto/trace [dpname] priority tun_id in_port mark packet */
+        const char *priority_s = adjusted_argv[0];
+        const char *tun_id_s = adjusted_argv[1];
+        const char *in_port_s = adjusted_argv[2];
+        const char *mark_s = adjusted_argv[3];
+        const char *packet_s = adjusted_argv[4];
         uint32_t in_port = atoi(in_port_s);
         ovs_be64 tun_id = htonll(strtoull(tun_id_s, NULL, 0));
         uint32_t priority = atoi(priority_s);
         uint32_t mark = atoi(mark_s);
         const char *msg;
+        const struct ofport_dpif *ofport;
+
+        /* Check the incorrect case:
+         * "ofproto/trace <bridge name> <metadata...> <packet>" */
+        if (has_name && !is_dp && argc == 7) {
+            unixctl_command_reply_error(conn, "Incorrect datapath name");
+            goto exit;
+        }
+
+        /* Extract the ofport_dpif object. */
+        ofport = odp_port_to_ofport(backer, in_port);
+
+        if (!ofport) {
+            unixctl_command_reply_error(conn, "Cannot find ofport, "
+                                        "from the given in_port");
+            goto exit;
+        }
+        if (!(ofport->bundle)) {
+            unixctl_command_reply_error(conn, "Cannot find the ofbundle "
+                                        "for the ofport");
+            goto exit;
+        }
+        /* Extract the ofproto_dpif object. */
+        ofproto = ofport->bundle->ofproto;
+        /* Convert the odp port to ofp port. */
+        in_port = ofport->up.ofp_port;
+
+        if (!ofproto) {
+            unixctl_command_reply_error(conn, "Unknown in_port number, "
+                                        "cannot find matched ofproto");
+            goto exit;
+        }
+
+        if (in_port == OFPP_NONE) {
+            unixctl_command_reply_error(conn, "Cannot convert datapath "
+                                        "port to openflow port.");
+            goto exit;
+       }
 
         msg = eth_from_hex(packet_s, &packet);
         if (msg) {
@@ -8670,8 +8758,10 @@ ofproto_dpif_unixctl_init(void)
 
     unixctl_command_register(
         "ofproto/trace",
-        "bridge {priority tun_id in_port mark packet | odp_flow [-generate]}",
-        2, 6, ofproto_unixctl_trace, NULL);
+        "[datapath] {priority tun_id in_port mark packet | "
+        "bridge of_flow [-generate]} | "
+        "[datapath] dp_flow [-generate]}",
+        1, 6, ofproto_unixctl_trace, NULL);
     unixctl_command_register("fdb/flush", "[bridge]", 0, 1,
                              ofproto_unixctl_fdb_flush, NULL);
     unixctl_command_register("fdb/show", "bridge", 1, 1,
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to