2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 01:51:26 +00:00

ofproto: Implement OFPT_QUEUE_GET_CONFIG_REQUEST for OFPP_ANY in OF1.1+.

I was not previously aware that this feature was missing.

Reported-by: Minoru TAKAHASHI <takahashi.minoru7@gmail.com>
Reported-at: http://openvswitch.org/pipermail/discuss/2015-October/019229.html
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Andy Zhou <azhou@ovn.org>
This commit is contained in:
Ben Pfaff 2016-01-07 08:57:44 -08:00
parent 5f4c5ff108
commit 56085be5fe
7 changed files with 103 additions and 43 deletions

3
NEWS
View File

@ -2,6 +2,9 @@ Post-v2.5.0
---------------------
- ovsdb-server:
* New "monitor2" and "update2" extensions to RFC 7047.
- OpenFlow:
* OpenFlow 1.1+ OFPT_QUEUE_GET_CONFIG_REQUEST now supports OFPP_ANY.
v2.5.0 - xx xxx xxxx
---------------------

View File

@ -2492,14 +2492,23 @@ ofputil_decode_queue_get_config_request(const struct ofp_header *oh,
case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST:
qgcr10 = b.data;
*port = u16_to_ofp(ntohs(qgcr10->port));
return 0;
break;
case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST:
qgcr11 = b.data;
return ofputil_port_from_ofp11(qgcr11->port, port);
enum ofperr error = ofputil_port_from_ofp11(qgcr11->port, port);
if (error || *port == OFPP_ANY) {
return error;
}
break;
default:
OVS_NOT_REACHED();
}
OVS_NOT_REACHED();
return (ofp_to_u16(*port) < ofp_to_u16(OFPP_MAX)
? 0
: OFPERR_OFPQOFC_BAD_PORT);
}
/* Constructs and returns the beginning of a reply to
@ -2576,15 +2585,10 @@ ofputil_append_queue_get_config_reply(struct ofpbuf *reply,
opq10->queue_id = htonl(oqc->queue_id);
len_ofs = (char *) &opq10->len - (char *) reply->data;
} else {
struct ofp11_queue_get_config_reply *qgcr11;
struct ofp12_packet_queue *opq12;
ovs_be32 port;
qgcr11 = reply->msg;
port = qgcr11->port;
opq12 = ofpbuf_put_zeros(reply, sizeof *opq12);
opq12->port = port;
opq12->port = ofputil_port_to_ofp11(oqc->port);
opq12->queue_id = htonl(oqc->queue_id);
len_ofs = (char *) &opq12->len - (char *) reply->data;
}

View File

@ -957,6 +957,7 @@ enum ofperr ofputil_decode_queue_get_config_request(const struct ofp_header *,
/* Queue configuration reply. */
struct ofputil_queue_config {
ofp_port_t port;
uint32_t queue_id;
/* Each of these optional values is expressed in tenths of a percent.

View File

@ -6230,30 +6230,12 @@ handle_group_features_stats_request(struct ofconn *ofconn,
return 0;
}
static enum ofperr
handle_queue_get_config_request(struct ofconn *ofconn,
const struct ofp_header *oh)
static void
put_queue_config(struct ofport *ofport, struct ofpbuf *reply)
{
struct ofproto *p = ofconn_get_ofproto(ofconn);
struct netdev_queue_dump queue_dump;
struct ofport *ofport;
unsigned int queue_id;
struct ofpbuf *reply;
struct smap details;
ofp_port_t request;
enum ofperr error;
error = ofputil_decode_queue_get_config_request(oh, &request);
if (error) {
return error;
}
ofport = ofproto_get_port(p, request);
if (!ofport) {
return OFPERR_OFPQOFC_BAD_PORT;
}
reply = ofputil_encode_queue_get_config_reply(oh);
smap_init(&details);
NETDEV_QUEUE_FOR_EACH (&queue_id, &details, &queue_dump, ofport->netdev) {
@ -6261,13 +6243,42 @@ handle_queue_get_config_request(struct ofconn *ofconn,
/* None of the existing queues have compatible properties, so we
* hard-code omitting min_rate and max_rate. */
queue.port = ofport->ofp_port;
queue.queue_id = queue_id;
queue.min_rate = UINT16_MAX;
queue.max_rate = UINT16_MAX;
ofputil_append_queue_get_config_reply(reply, &queue);
}
smap_destroy(&details);
}
static enum ofperr
handle_queue_get_config_request(struct ofconn *ofconn,
const struct ofp_header *oh)
{
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
ofp_port_t port;
enum ofperr error;
error = ofputil_decode_queue_get_config_request(oh, &port);
if (error) {
return error;
}
struct ofpbuf *reply = ofputil_encode_queue_get_config_reply(oh);
struct ofport *ofport;
if (port == OFPP_ANY) {
HMAP_FOR_EACH (ofport, hmap_node, &ofproto->ports) {
put_queue_config(ofport, reply);
}
} else {
ofport = ofproto_get_port(ofproto, port);
if (!ofport) {
ofpbuf_delete(reply);
return OFPERR_OFPQOFC_BAD_PORT;
}
put_queue_config(ofport, reply);
}
ofconn_send_reply(ofconn, reply);
return 0;

View File

@ -240,6 +240,11 @@ AT_CHECK([ovs-ofctl queue-get-config br0 1], [0], [stdout])
AT_CHECK([STRIP_XIDS stdout], [0], [dnl
OFPT_QUEUE_GET_CONFIG_REPLY: port=1
])
AT_CHECK([ovs-ofctl queue-get-config br0], [0], [stdout])
AT_CHECK([STRIP_XIDS stdout | sort], [0], [dnl
OFPT_QUEUE_GET_CONFIG_REPLY: port=1
OFPT_QUEUE_GET_CONFIG_REPLY: port=2
])
AT_CHECK([ovs-ofctl queue-get-config br0 10], [0],
[OFPT_ERROR (xid=0x2): OFPQOFC_BAD_PORT
OFPT_QUEUE_GET_CONFIG_REQUEST (xid=0x2): port=10
@ -254,6 +259,10 @@ AT_CHECK([ovs-ofctl -O OpenFlow12 queue-get-config br0 1], [0], [stdout])
AT_CHECK([STRIP_XIDS stdout], [0], [dnl
OFPT_QUEUE_GET_CONFIG_REPLY (OF1.2): port=1
])
AT_CHECK([ovs-ofctl -O OpenFlow12 queue-get-config br0 ANY], [0], [stdout])
AT_CHECK([STRIP_XIDS stdout], [0], [dnl
OFPT_QUEUE_GET_CONFIG_REPLY (OF1.2): port=ANY
])
AT_CHECK([ovs-ofctl -O OpenFlow12 queue-get-config br0 10], [0],
[OFPT_ERROR (OF1.2) (xid=0x2): OFPQOFC_BAD_PORT
OFPT_QUEUE_GET_CONFIG_REQUEST (OF1.2) (xid=0x2): port=10

View File

@ -244,6 +244,17 @@ statistics are printed for all queues on \fIport\fR; if only
\fIport\fR is omitted, then statistics are printed for \fIqueue\fR on
every port where it exists.
.
.IP "\fBqueue\-get\-config \fIswitch \fR[\fIport\fR]"
Prints to the console information about all of the queues configured
on \fIport\fR within \fIswitch\fR. If \fIport\fR is \fBANY\fR or if
it is omitted, prints information about queues on every port. The
OpenFlow specification says that only physical ports have queues; in
particular, \fBLOCAL\fR is not valid for \fIport\fR.
.IP
This command has limited usefulness, because ports often have no
configured queues and because the OpenFlow protocol provides only very
limited information about the configuration of a queue.
.
.SS "OpenFlow 1.1+ Group Table Commands"
.
The following commands work only with switches that support OpenFlow

View File

@ -378,7 +378,7 @@ usage(void)
" dump-group-features SWITCH print group features\n"
" dump-groups SWITCH [GROUP] print group description\n"
" dump-group-stats SWITCH [GROUP] print group statistics\n"
" queue-get-config SWITCH PORT print queue information for port\n"
" queue-get-config SWITCH [PORT] print queue config for PORT\n"
" add-meter SWITCH METER add meter described by METER\n"
" mod-meter SWITCH METER modify specific METER\n"
" del-meter SWITCH METER delete METER\n"
@ -1252,19 +1252,40 @@ static void
ofctl_queue_get_config(struct ovs_cmdl_context *ctx)
{
const char *vconn_name = ctx->argv[1];
const char *port_name = ctx->argv[2];
enum ofputil_protocol protocol;
enum ofp_version version;
struct ofpbuf *request;
const char *port_name = ctx->argc >= 3 ? ctx->argv[2] : NULL;
ofp_port_t port = (port_name
? str_to_port_no(vconn_name, port_name)
: OFPP_ANY);
struct vconn *vconn;
ofp_port_t port;
enum ofputil_protocol protocol = open_vconn(vconn_name, &vconn);
enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
if (port == OFPP_ANY && version == OFP10_VERSION) {
/* The user requested all queues on all ports. OpenFlow 1.0 only
* supports getting queues for an individual port, so to implement the
* user's request we have to get a list of all the ports.
*
* We use a second vconn to avoid having to accumulate a list of all of
* the ports. */
struct vconn *vconn2;
enum ofputil_protocol protocol2 = open_vconn(vconn_name, &vconn2);
enum ofp_version version2 = ofputil_protocol_to_ofp_version(protocol2);
port = str_to_port_no(vconn_name, port_name);
protocol = open_vconn(vconn_name, &vconn);
version = ofputil_protocol_to_ofp_version(protocol);
request = ofputil_encode_queue_get_config_request(version, port);
dump_transaction(vconn, request);
struct port_iterator pi;
struct ofputil_phy_port pp;
for (port_iterator_init(&pi, vconn); port_iterator_next(&pi, &pp); ) {
if (ofp_to_u16(pp.port_no) < ofp_to_u16(OFPP_MAX)) {
dump_transaction(vconn2,
ofputil_encode_queue_get_config_request(
version2, pp.port_no));
}
}
port_iterator_destroy(&pi);
vconn_close(vconn2);
} else {
dump_transaction(vconn, ofputil_encode_queue_get_config_request(
version, port));
}
vconn_close(vconn);
}
@ -3870,8 +3891,8 @@ static const struct ovs_cmdl_command all_commands[] = {
1, 2, ofctl_dump_aggregate },
{ "queue-stats", "switch [port [queue]]",
1, 3, ofctl_queue_stats },
{ "queue-get-config", "switch port",
2, 2, ofctl_queue_get_config },
{ "queue-get-config", "switch [port]",
1, 2, ofctl_queue_get_config },
{ "add-flow", "switch flow",
2, 2, ofctl_add_flow },
{ "add-flows", "switch file",