Not all ports may fit in a Features Reply, so use the new port
description stat message instead for looking up ports.

Signed-off-by: Justin Pettit <[email protected]>
---
 utilities/ovs-ofctl.c |   77 +++++++++++++++++++++++++++++++++----------------
 1 files changed, 52 insertions(+), 25 deletions(-)

diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index d94ad64..3b244d8 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -536,50 +536,77 @@ do_dump_tables(int argc OVS_UNUSED, char *argv[])
 
 /* 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
- * '*oppp'. */
+ * '*pp'. */
 static void
 fetch_ofputil_phy_port(const char *vconn_name, const char *port_name,
                        struct ofputil_phy_port *pp)
 {
-    struct ofputil_switch_features features;
-    const struct ofp_switch_features *osf;
-    struct ofpbuf *request, *reply;
+    struct ofpbuf *request;
     unsigned int port_no;
     struct vconn *vconn;
     enum ofperr error;
+    ovs_be32 send_xid;
     struct ofpbuf b;
+    bool done = false;
+    bool found = false;
 
     /* Try to interpret the argument as a port number. */
     if (!str_to_uint(port_name, 10, &port_no)) {
         port_no = UINT_MAX;
     }
 
-    /* Fetch the switch's ofp_switch_features. */
-    make_openflow(sizeof(struct ofp_header), OFPT_FEATURES_REQUEST, &request);
+    alloc_stats_request(sizeof(struct ofp_stats_msg), OFPST_PORT_DESC,
+                        &request);
+    send_xid = ((struct ofp_header *) request->data)->xid;
+
     open_vconn(vconn_name, &vconn);
-    run(vconn_transact(vconn, request, &reply), "talking to %s", vconn_name);
+    send_openflow_buffer(vconn, request);
+    while (!done) {
+        ovs_be32 recv_xid;
+        struct ofpbuf *reply;
 
-    osf = reply->data;
-    if (reply->size < sizeof *osf) {
-        ovs_fatal(0, "%s: received too-short features reply (only %zu bytes)",
-                  vconn_name, reply->size);
-    }
-    error = ofputil_decode_switch_features(osf, &features, &b);
-    if (error) {
-        ovs_fatal(0, "%s: failed to decode features reply (%s)",
-                  vconn_name, ofperr_to_string(error));
-    }
+        run(vconn_recv_block(vconn, &reply), "OpenFlow packet receive failed");
+        recv_xid = ((struct ofp_header *) reply->data)->xid;
+        if (send_xid == recv_xid) {
+            struct ofp_stats_msg *osm;
+            size_t n_ports;
+            int i;
 
-    while (!ofputil_pull_phy_port(osf->header.version, &b, pp)) {
-        if (port_no != UINT_MAX
-            ? port_no == pp->port_no
-            : !strcmp(pp->name, port_name)) {
-            ofpbuf_delete(reply);
-            vconn_close(vconn);
-            return;
+            osm = ofpbuf_at(reply, 0, sizeof *osm);
+            done = !osm || !(ntohs(osm->flags) & OFPSF_REPLY_MORE);
+
+            if (found) {
+                /* We've already found the port, but we need to drain
+                 * the queue of any other replies for this request. */
+                continue;
+            }
+
+            ofpbuf_use_const(&b, &osm->header, ntohs(osm->header.length));
+            ofpbuf_pull(&b, sizeof(struct ofp_stats_msg));
+
+            n_ports = ofputil_count_phy_ports(osm->header.version, &b);
+            for (i = 0; i < n_ports; i++) {
+                error = ofputil_pull_phy_port(osm->header.version, &b, pp);
+                if (error) {
+                    ovs_fatal(0, "%s: problem retrieving ports", vconn_name);
+                }
+                if (port_no != UINT_MAX ? port_no == pp->port_no
+                                        : !strcmp(pp->name, port_name)) {
+                    found = true;
+                    break;
+                }
+            }
+        } else {
+            VLOG_DBG("received reply with xid %08"PRIx32" "
+                     "!= expected %08"PRIx32, recv_xid, send_xid);
         }
+        ofpbuf_delete(reply);
+    }
+    vconn_close(vconn);
+
+    if (!found) {
+        ovs_fatal(0, "%s: couldn't find port `%s'", vconn_name, port_name);
     }
-    ovs_fatal(0, "%s: couldn't find port `%s'", vconn_name, port_name);
 }
 
 /* Returns the port number corresponding to 'port_name' (which may be a port
-- 
1.7.5.4

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to