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
