2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-03 07:45:30 +00:00

Implement OpenFlow 1.5 port desc stats request.

OpenFlow 1.4 and earlier always send the description of every port in
response to an OFPMP_PORT_DESC request.  OpenFlow 1.5 proposes allowing
the controller to request a description of a single port.  This commit
implements a prototype.

EXT-69.
Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Ben Pfaff
2014-05-07 23:18:46 -07:00
parent 19187a715f
commit 70ae4f930c
9 changed files with 193 additions and 41 deletions

View File

@@ -367,8 +367,10 @@ enum ofpraw {
/* OFPST 1.3+ (12): struct ofp13_table_features, uint8_t[8][]. */
OFPRAW_OFPST13_TABLE_FEATURES_REPLY,
/* OFPST 1.0+ (13): void. */
OFPRAW_OFPST_PORT_DESC_REQUEST,
/* OFPST 1.0-1.4 (13): void. */
OFPRAW_OFPST10_PORT_DESC_REQUEST,
/* OFPST 1.5+ (13): ovs_be32. */
OFPRAW_OFPST15_PORT_DESC_REQUEST,
/* OFPST 1.0 (13): struct ofp10_phy_port[]. */
OFPRAW_OFPST10_PORT_DESC_REPLY,
@@ -598,7 +600,8 @@ enum ofptype {
OFPTYPE_TABLE_FEATURES_STATS_REPLY, /* OFPRAW_OFPST13_TABLE_FEATURES_REPLY. */
OFPTYPE_PORT_DESC_STATS_REQUEST, /* OFPRAW_OFPST_PORT_DESC_REQUEST. */
OFPTYPE_PORT_DESC_STATS_REQUEST, /* OFPRAW_OFPST10_PORT_DESC_REQUEST.
* OFPRAW_OFPST15_PORT_DESC_REQUEST. */
OFPTYPE_PORT_DESC_STATS_REPLY, /* OFPRAW_OFPST10_PORT_DESC_REPLY.
* OFPRAW_OFPST11_PORT_DESC_REPLY.

View File

@@ -1899,6 +1899,23 @@ ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
}
}
static void
ofp_print_ofpst_port_desc_request(struct ds *string,
const struct ofp_header *oh)
{
enum ofperr error;
ofp_port_t port;
error = ofputil_decode_port_desc_stats_request(oh, &port);
if (error) {
ofp_print_error(string, error);
return;
}
ds_put_cstr(string, " port=");
ofputil_format_port(port, string);
}
static void
ofp_print_ofpst_port_desc_reply(struct ds *string,
const struct ofp_header *oh)
@@ -2917,7 +2934,6 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
break;
case OFPTYPE_DESC_STATS_REQUEST:
case OFPTYPE_PORT_DESC_STATS_REQUEST:
case OFPTYPE_METER_FEATURES_STATS_REQUEST:
ofp_print_stats_request(string, oh);
break;
@@ -2972,6 +2988,11 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
ofp_print_aggregate_stats_reply(string, oh);
break;
case OFPTYPE_PORT_DESC_STATS_REQUEST:
ofp_print_stats_request(string, oh);
ofp_print_ofpst_port_desc_request(string, oh);
break;
case OFPTYPE_PORT_DESC_STATS_REPLY:
ofp_print_stats_reply(string, oh);
ofp_print_ofpst_port_desc_reply(string, oh);

View File

@@ -3928,6 +3928,59 @@ ofputil_put_phy_port(enum ofp_version ofp_version,
}
}
enum ofperr
ofputil_decode_port_desc_stats_request(const struct ofp_header *request,
ofp_port_t *port)
{
struct ofpbuf b;
enum ofpraw raw;
ofpbuf_use_const(&b, request, ntohs(request->length));
raw = ofpraw_pull_assert(&b);
if (raw == OFPRAW_OFPST10_PORT_DESC_REQUEST) {
*port = OFPP_ANY;
return 0;
} else if (raw == OFPRAW_OFPST15_PORT_DESC_REQUEST) {
ovs_be32 *ofp11_port;
ofp11_port = ofpbuf_pull(&b, sizeof *ofp11_port);
return ofputil_port_from_ofp11(*ofp11_port, port);
} else {
OVS_NOT_REACHED();
}
}
struct ofpbuf *
ofputil_encode_port_desc_stats_request(enum ofp_version ofp_version,
ofp_port_t port)
{
struct ofpbuf *request;
ovs_be32 ofp11_port;
switch (ofp_version) {
case OFP10_VERSION:
case OFP11_VERSION:
case OFP12_VERSION:
case OFP13_VERSION:
case OFP14_VERSION:
request = ofpraw_alloc(OFPRAW_OFPST10_PORT_DESC_REQUEST,
ofp_version, 0);
break;
case OFP15_VERSION:
request = ofpraw_alloc(OFPRAW_OFPST15_PORT_DESC_REQUEST,
ofp_version, 0);
ofp11_port = ofputil_port_to_ofp11(port);
ofpbuf_put(request, &ofp11_port, sizeof ofp11_port);
break;
default:
OVS_NOT_REACHED();
}
return request;
}
void
ofputil_append_port_desc_stats_reply(const struct ofputil_phy_port *pp,
struct list *replies)

View File

@@ -875,7 +875,12 @@ void ofputil_append_flow_update(const struct ofputil_flow_update *,
uint32_t ofputil_decode_flow_monitor_cancel(const struct ofp_header *);
struct ofpbuf *ofputil_encode_flow_monitor_cancel(uint32_t id);
/* Encoding OpenFlow stats messages. */
/* Port desc stats requests and replies. */
enum ofperr ofputil_decode_port_desc_stats_request(const struct ofp_header *,
ofp_port_t *portp);
struct ofpbuf *ofputil_encode_port_desc_stats_request(
enum ofp_version ofp_version, ofp_port_t);
void ofputil_append_port_desc_stats_reply(const struct ofputil_phy_port *pp,
struct list *replies);

View File

@@ -3170,52 +3170,62 @@ append_port_stat(struct ofport *port, struct list *replies)
ofputil_append_port_stat(replies, &ops);
}
static enum ofperr
handle_port_stats_request(struct ofconn *ofconn,
const struct ofp_header *request)
static void
handle_port_request(struct ofconn *ofconn,
const struct ofp_header *request, ofp_port_t port_no,
void (*cb)(struct ofport *, struct list *replies))
{
struct ofproto *p = ofconn_get_ofproto(ofconn);
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
struct ofport *port;
struct list replies;
ofp_port_t port_no;
enum ofperr error;
error = ofputil_decode_port_stats_request(request, &port_no);
if (error) {
return error;
}
ofpmp_init(&replies, request);
if (port_no != OFPP_ANY) {
port = ofproto_get_port(p, port_no);
port = ofproto_get_port(ofproto, port_no);
if (port) {
append_port_stat(port, &replies);
cb(port, &replies);
}
} else {
HMAP_FOR_EACH (port, hmap_node, &p->ports) {
append_port_stat(port, &replies);
HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
cb(port, &replies);
}
}
ofconn_send_replies(ofconn, &replies);
return 0;
}
static enum ofperr
handle_port_stats_request(struct ofconn *ofconn,
const struct ofp_header *request)
{
ofp_port_t port_no;
enum ofperr error;
error = ofputil_decode_port_stats_request(request, &port_no);
if (!error) {
handle_port_request(ofconn, request, port_no, append_port_stat);
}
return error;
}
static void
append_port_desc(struct ofport *port, struct list *replies)
{
ofputil_append_port_desc_stats_reply(&port->pp, replies);
}
static enum ofperr
handle_port_desc_stats_request(struct ofconn *ofconn,
const struct ofp_header *request)
{
struct ofproto *p = ofconn_get_ofproto(ofconn);
struct ofport *port;
struct list replies;
ofp_port_t port_no;
enum ofperr error;
ofpmp_init(&replies, request);
HMAP_FOR_EACH (port, hmap_node, &p->ports) {
ofputil_append_port_desc_stats_reply(&port->pp, &replies);
error = ofputil_decode_port_desc_stats_request(request, &port_no);
if (!error) {
handle_port_request(ofconn, request, port_no, append_port_desc);
}
ofconn_send_replies(ofconn, &replies);
return 0;
return error;
}
static uint32_t

View File

@@ -1943,7 +1943,16 @@ AT_CLEANUP
AT_SETUP([OFPST_PORT_DESC request - OF1.0])
AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
AT_CHECK([ovs-ofctl ofp-print "0110000c00000001000d0000"], [0], [dnl
OFPST_PORT_DESC request (xid=0x1):
OFPST_PORT_DESC request (xid=0x1): port=ANY
])
AT_CLEANUP
AT_SETUP([OFPST_PORT_DESC request - OF1.5])
AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
AT_CHECK([ovs-ofctl ofp-print "\
06 12 00 14 00 00 00 02 00 0d 00 00 00 00 00 00 \
00 00 00 05"], [0], [dnl
OFPST_PORT_DESC request (OF1.5) (xid=0x2): port=5
])
AT_CLEANUP

View File

@@ -144,6 +144,40 @@ OFPST_PORT_DESC reply (OF1.2):
OVS_VSWITCHD_STOP
AT_CLEANUP
AT_SETUP([ofproto - port-desc stats (OpenFlow 1.5)])
OVS_VSWITCHD_START
ADD_OF_PORTS([br0], 1, 2, 3)
AT_CHECK([ovs-ofctl -F OXM-OpenFlow15 -O OpenFlow15 -vwarn dump-ports-desc br0], [0], [stdout])
AT_CHECK([STRIP_XIDS stdout | sed 's/00:0./00:0x/'], [0], [dnl
OFPST_PORT_DESC reply (OF1.5):
1(p1): addr:aa:55:aa:55:00:0x
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
2(p2): addr:aa:55:aa:55:00:0x
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
3(p3): addr:aa:55:aa:55:00:0x
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
LOCAL(br0): addr:aa:55:aa:55:00:0x
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
])
AT_CHECK([ovs-ofctl -F OXM-OpenFlow15 -O OpenFlow15 -vwarn dump-ports-desc br0 2], [0], [stdout])
AT_CHECK([STRIP_XIDS stdout | sed 's/00:0./00:0x/'], [0], [dnl
OFPST_PORT_DESC reply (OF1.5):
2(p2): addr:aa:55:aa:55:00:0x
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
])
OVS_VSWITCHD_STOP
AT_CLEANUP
dnl This is really bare-bones.
dnl It at least checks request and reply serialization and deserialization.
AT_SETUP([ofproto - queue stats - (OpenFlow 1.0)])

View File

@@ -70,11 +70,19 @@ Prints to the console statistics for network devices associated with
associated with that device will be printed. \fInetdev\fR can be an
OpenFlow assigned port number or device name, e.g. \fBeth0\fR.
.
.TP
\fBdump\-ports\-desc \fIswitch\fR
.IP "\fBdump\-ports\-desc \fIswitch\fR [\fIport\fR]"
Prints to the console detailed information about network devices
associated with \fIswitch\fR (version 1.7 or later). This is a subset
of the information provided by the \fBshow\fR command.
associated with \fIswitch\fR. To dump only a specific port, specify
its number as \fIport\fR. Otherwise, if \fIport\fR is omitted, or if
it is specified as \fBANY\fR, then all ports are printed. This is a
subset of the information provided by the \fBshow\fR command.
.IP
If the connection to \fIswitch\fR negotiates OpenFlow 1.0, 1.2, or
1.2, this command uses an OpenFlow extension only implemented in Open
vSwitch (version 1.7 and later).
.IP
Only OpenFlow 1.5 and later support dumping a specific port. Earlier
versions of OpenFlow always dump all ports.
.
.IP "\fBmod\-port \fIswitch\fR \fIport\fR \fIaction\fR"
Modify characteristics of port \fBport\fR in \fIswitch\fR. \fIport\fR

View File

@@ -305,7 +305,7 @@ usage(void)
" get-frags SWITCH print fragment handling behavior\n"
" set-frags SWITCH FRAG_MODE set fragment handling behavior\n"
" dump-ports SWITCH [PORT] print port statistics\n"
" dump-ports-desc SWITCH print port descriptions\n"
" dump-ports-desc SWITCH [PORT] print port descriptions\n"
" dump-flows SWITCH print all flow entries\n"
" dump-flows SWITCH FLOW print matching FLOWs\n"
" dump-aggregate SWITCH print aggregate flow statistics\n"
@@ -648,7 +648,7 @@ ofctl_show(int argc OVS_UNUSED, char *argv[])
ofpbuf_delete(reply);
if (!has_ports) {
request = ofpraw_alloc(OFPRAW_OFPST_PORT_DESC_REQUEST, version, 0);
request = ofputil_encode_port_desc_stats_request(version, OFPP_ANY);
dump_stats_transaction(vconn, request);
}
dump_trivial_transaction(vconn_name, OFPRAW_OFPT_GET_CONFIG_REQUEST);
@@ -761,8 +761,8 @@ fetch_port_by_stats(struct vconn *vconn,
bool done = false;
bool found = false;
request = ofpraw_alloc(OFPRAW_OFPST_PORT_DESC_REQUEST,
vconn_get_version(vconn), 0);
request = ofputil_encode_port_desc_stats_request(vconn_get_version(vconn),
port_no);
send_xid = ((struct ofp_header *) ofpbuf_data(request))->xid;
send_openflow_buffer(vconn, request);
@@ -1620,7 +1620,16 @@ ofctl_dump_ports(int argc, char *argv[])
static void
ofctl_dump_ports_desc(int argc OVS_UNUSED, char *argv[])
{
dump_trivial_stats_transaction(argv[1], OFPRAW_OFPST_PORT_DESC_REQUEST);
struct ofpbuf *request;
struct vconn *vconn;
ofp_port_t port;
open_vconn(argv[1], &vconn);
port = argc > 2 ? str_to_port_no(argv[1], argv[2]) : OFPP_ANY;
request = ofputil_encode_port_desc_stats_request(vconn_get_version(vconn),
port);
dump_stats_transaction(vconn, request);
vconn_close(vconn);
}
static void
@@ -3504,7 +3513,7 @@ static const struct command all_commands[] = {
{ "meter-features", 1, 1, ofctl_meter_features },
{ "packet-out", 4, INT_MAX, ofctl_packet_out },
{ "dump-ports", 1, 2, ofctl_dump_ports },
{ "dump-ports-desc", 1, 1, ofctl_dump_ports_desc },
{ "dump-ports-desc", 1, 2, ofctl_dump_ports_desc },
{ "mod-port", 3, 3, ofctl_mod_port },
{ "mod-table", 3, 3, ofctl_mod_table },
{ "get-frags", 1, 1, ofctl_get_frags },