mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 06:15:47 +00:00
openflow: Make stats replies more like other OpenFlow messages.
This commit is contained in:
@@ -154,10 +154,7 @@ enum nicira_type {
|
||||
|
||||
/* Header for Nicira vendor stats request and reply messages. */
|
||||
struct nicira_stats_msg {
|
||||
struct ofp_header header; /* OFPT_STATS_REQUEST or OFPT_STATS_REPLY. */
|
||||
ovs_be16 type; /* OFPST_VENDOR. */
|
||||
ovs_be16 flags; /* OFPSF_{REQ,REPLY}_*. */
|
||||
ovs_be32 vendor; /* NX_VENDOR_ID. */
|
||||
struct ofp_vendor_stats_msg vsm; /* Vendor NX_VENDOR_ID. */
|
||||
ovs_be32 subtype; /* One of NXST_* below. */
|
||||
uint8_t pad[4]; /* Align to 64-bits. */
|
||||
};
|
||||
|
@@ -696,39 +696,37 @@ OFP_ASSERT(sizeof(struct ofp_error_msg) == 12);
|
||||
|
||||
enum ofp_stats_types {
|
||||
/* Description of this OpenFlow switch.
|
||||
* The request body is empty.
|
||||
* The reply body is struct ofp_desc_stats. */
|
||||
* The request is struct ofp_stats_msg.
|
||||
* The reply is struct ofp_desc_stats. */
|
||||
OFPST_DESC,
|
||||
|
||||
/* Individual flow statistics.
|
||||
* The request body is struct ofp_flow_stats_request.
|
||||
* The request is struct ofp_flow_stats_request.
|
||||
* The reply body is an array of struct ofp_flow_stats. */
|
||||
OFPST_FLOW,
|
||||
|
||||
/* Aggregate flow statistics.
|
||||
* The request body is struct ofp_flow_stats_request.
|
||||
* The reply body is struct ofp_aggregate_stats_reply. */
|
||||
* The request is struct ofp_flow_stats_request.
|
||||
* The reply is struct ofp_aggregate_stats_reply. */
|
||||
OFPST_AGGREGATE,
|
||||
|
||||
/* Flow table statistics.
|
||||
* The request body is empty.
|
||||
* The request is struct ofp_stats_msg.
|
||||
* The reply body is an array of struct ofp_table_stats. */
|
||||
OFPST_TABLE,
|
||||
|
||||
/* Physical port statistics.
|
||||
* The request body is struct ofp_port_stats_request.
|
||||
* The request is struct ofp_port_stats_request.
|
||||
* The reply body is an array of struct ofp_port_stats. */
|
||||
OFPST_PORT,
|
||||
|
||||
/* Queue statistics for a port
|
||||
/* Queue statistics for a port.
|
||||
* The request body is struct ofp_queue_stats_request.
|
||||
* The reply body is an array of struct ofp_queue_stats. */
|
||||
OFPST_QUEUE,
|
||||
|
||||
/* Vendor extension.
|
||||
* The request and reply bodies begin with a 32-bit vendor ID, which takes
|
||||
* the same form as in "struct ofp_vendor_header". The request and reply
|
||||
* bodies are otherwise vendor-defined. */
|
||||
* The request and reply begin with "struct ofp_vendor_stats". */
|
||||
OFPST_VENDOR = 0xffff
|
||||
};
|
||||
|
||||
@@ -747,9 +745,10 @@ enum ofp_stats_reply_flags {
|
||||
|
||||
#define DESC_STR_LEN 256
|
||||
#define SERIAL_NUM_LEN 32
|
||||
/* Body of reply to OFPST_DESC request. Each entry is a NULL-terminated
|
||||
* ASCII string. */
|
||||
/* Reply to OFPST_DESC request. Each entry is a NULL-terminated ASCII
|
||||
* string. */
|
||||
struct ofp_desc_stats {
|
||||
struct ofp_stats_msg osm;
|
||||
char mfr_desc[DESC_STR_LEN]; /* Manufacturer description. */
|
||||
char hw_desc[DESC_STR_LEN]; /* Hardware description. */
|
||||
char sw_desc[DESC_STR_LEN]; /* Software description. */
|
||||
@@ -757,10 +756,11 @@ struct ofp_desc_stats {
|
||||
char dp_desc[DESC_STR_LEN]; /* Human readable description of
|
||||
the datapath. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_desc_stats) == 1056);
|
||||
OFP_ASSERT(sizeof(struct ofp_desc_stats) == 1068);
|
||||
|
||||
/* Body for stats request of type OFPST_FLOW or OFPST_AGGREGATE. */
|
||||
/* Stats request of type OFPST_AGGREGATE or OFPST_FLOW. */
|
||||
struct ofp_flow_stats_request {
|
||||
struct ofp_stats_msg osm;
|
||||
struct ofp_match match; /* Fields to match. */
|
||||
uint8_t table_id; /* ID of table to read (from ofp_table_stats)
|
||||
or 0xff for all tables. */
|
||||
@@ -769,7 +769,7 @@ struct ofp_flow_stats_request {
|
||||
as an output port. A value of OFPP_NONE
|
||||
indicates no restriction. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_flow_stats_request) == 44);
|
||||
OFP_ASSERT(sizeof(struct ofp_flow_stats_request) == 56);
|
||||
|
||||
/* Body of reply to OFPST_FLOW request. */
|
||||
struct ofp_flow_stats {
|
||||
@@ -792,14 +792,15 @@ struct ofp_flow_stats {
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_flow_stats) == 88);
|
||||
|
||||
/* Body of reply to OFPST_AGGREGATE request. */
|
||||
/* Reply to OFPST_AGGREGATE request. */
|
||||
struct ofp_aggregate_stats_reply {
|
||||
struct ofp_stats_msg osm;
|
||||
ovs_32aligned_be64 packet_count; /* Number of packets in flows. */
|
||||
ovs_32aligned_be64 byte_count; /* Number of bytes in flows. */
|
||||
ovs_be32 flow_count; /* Number of flows. */
|
||||
uint8_t pad[4]; /* Align to 64 bits. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24);
|
||||
OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 36);
|
||||
|
||||
/* Body of reply to OFPST_TABLE request. */
|
||||
struct ofp_table_stats {
|
||||
@@ -816,14 +817,15 @@ struct ofp_table_stats {
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_table_stats) == 64);
|
||||
|
||||
/* Body for stats request of type OFPST_PORT. */
|
||||
/* Stats request of type OFPST_PORT. */
|
||||
struct ofp_port_stats_request {
|
||||
struct ofp_stats_msg osm;
|
||||
ovs_be16 port_no; /* OFPST_PORT message may request statistics
|
||||
for a single port (specified with port_no)
|
||||
or for all ports (port_no == OFPP_NONE). */
|
||||
uint8_t pad[6];
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_port_stats_request) == 8);
|
||||
OFP_ASSERT(sizeof(struct ofp_port_stats_request) == 20);
|
||||
|
||||
/* Body of reply to OFPST_PORT request. If a counter is unsupported, set
|
||||
* the field to all ones. */
|
||||
@@ -854,11 +856,12 @@ OFP_ASSERT(sizeof(struct ofp_port_stats) == 104);
|
||||
|
||||
/* Body for stats request of type OFPST_QUEUE. */
|
||||
struct ofp_queue_stats_request {
|
||||
struct ofp_stats_msg osm;
|
||||
ovs_be16 port_no; /* All ports if OFPP_ALL. */
|
||||
uint8_t pad[2]; /* Align to 32-bits. */
|
||||
ovs_be32 queue_id; /* All queues if OFPQ_ALL. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_queue_stats_request) == 8);
|
||||
OFP_ASSERT(sizeof(struct ofp_queue_stats_request) == 20);
|
||||
|
||||
/* Body for stats reply of type OFPST_QUEUE consists of an array of this
|
||||
* structure type. */
|
||||
@@ -872,6 +875,17 @@ struct ofp_queue_stats {
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_queue_stats) == 32);
|
||||
|
||||
/* Vendor extension stats message. */
|
||||
struct ofp_vendor_stats_msg {
|
||||
struct ofp_stats_msg osm; /* Type OFPST_VENDOR. */
|
||||
ovs_be32 vendor; /* Vendor ID:
|
||||
* - MSB 0: low-order bytes are IEEE OUI.
|
||||
* - MSB != 0: defined by OpenFlow
|
||||
* consortium. */
|
||||
/* Followed by vendor-defined arbitrary additional data. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_vendor_stats_msg) == 16);
|
||||
|
||||
/* Vendor extension. */
|
||||
struct ofp_vendor_header {
|
||||
struct ofp_header header; /* Type OFPT_VENDOR. */
|
||||
|
@@ -1043,10 +1043,8 @@ ofp_print_port_status(struct ds *string, const struct ofp_port_status *ops)
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh)
|
||||
ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_desc_stats *ods)
|
||||
{
|
||||
const struct ofp_desc_stats *ods = ofputil_stats_body(oh);
|
||||
|
||||
ds_put_char(string, '\n');
|
||||
ds_put_format(string, "Manufacturer: %.*s\n",
|
||||
(int) sizeof ods->mfr_desc, ods->mfr_desc);
|
||||
@@ -1131,8 +1129,8 @@ ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh)
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_print_ofp_aggregate_stats_reply (
|
||||
struct ds *string, const struct ofp_aggregate_stats_reply *asr)
|
||||
ofp_print_ofpst_aggregate_reply(struct ds *string,
|
||||
const struct ofp_aggregate_stats_reply *asr)
|
||||
{
|
||||
ds_put_format(string, " packet_count=%"PRIu64,
|
||||
ntohll(get_32aligned_be64(&asr->packet_count)));
|
||||
@@ -1141,12 +1139,6 @@ ofp_print_ofp_aggregate_stats_reply (
|
||||
ds_put_format(string, " flow_count=%"PRIu32, ntohl(asr->flow_count));
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_print_ofpst_aggregate_reply(struct ds *string, const struct ofp_header *oh)
|
||||
{
|
||||
ofp_print_ofp_aggregate_stats_reply(string, ofputil_stats_body(oh));
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_print_nxst_aggregate_reply(struct ds *string,
|
||||
const struct nx_aggregate_stats_reply *nasr)
|
||||
@@ -1175,9 +1167,9 @@ static void print_port_stat(struct ds *string, const char *leader,
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh)
|
||||
ofp_print_ofpst_port_request(struct ds *string,
|
||||
const struct ofp_port_stats_request *psr)
|
||||
{
|
||||
const struct ofp_port_stats_request *psr = ofputil_stats_body(oh);
|
||||
ds_put_format(string, " port_no=%"PRIu16, ntohs(psr->port_no));
|
||||
}
|
||||
|
||||
@@ -1251,10 +1243,9 @@ ofp_print_queue_name(struct ds *string, uint32_t queue_id)
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh)
|
||||
ofp_print_ofpst_queue_request(struct ds *string,
|
||||
const struct ofp_queue_stats_request *qsr)
|
||||
{
|
||||
const struct ofp_queue_stats_request *qsr = ofputil_stats_body(oh);
|
||||
|
||||
ds_put_cstr(string, "port=");
|
||||
ofp_print_port_name(string, ntohs(qsr->port_no));
|
||||
|
||||
@@ -1465,17 +1456,17 @@ ofp_to_string__(const struct ofp_header *oh,
|
||||
|
||||
case OFPUTIL_OFPST_PORT_REQUEST:
|
||||
ofp_print_stats_request(string, oh);
|
||||
ofp_print_ofpst_port_request(string, oh);
|
||||
ofp_print_ofpst_port_request(string, msg);
|
||||
break;
|
||||
|
||||
case OFPUTIL_OFPST_QUEUE_REQUEST:
|
||||
ofp_print_stats_request(string, oh);
|
||||
ofp_print_ofpst_queue_request(string, oh);
|
||||
ofp_print_ofpst_queue_request(string, msg);
|
||||
break;
|
||||
|
||||
case OFPUTIL_OFPST_DESC_REPLY:
|
||||
ofp_print_stats_reply(string, oh);
|
||||
ofp_print_ofpst_desc_reply(string, oh);
|
||||
ofp_print_ofpst_desc_reply(string, msg);
|
||||
break;
|
||||
|
||||
case OFPUTIL_OFPST_FLOW_REPLY:
|
||||
@@ -1501,7 +1492,7 @@ ofp_to_string__(const struct ofp_header *oh,
|
||||
|
||||
case OFPUTIL_OFPST_AGGREGATE_REPLY:
|
||||
ofp_print_stats_reply(string, oh);
|
||||
ofp_print_ofpst_aggregate_reply(string, oh);
|
||||
ofp_print_ofpst_aggregate_reply(string, msg);
|
||||
break;
|
||||
|
||||
case OFPUTIL_NXT_ROLE_REQUEST:
|
||||
|
177
lib/ofp-util.c
177
lib/ofp-util.c
@@ -500,35 +500,34 @@ static int
|
||||
ofputil_decode_ofpst_request(const struct ofp_header *oh,
|
||||
const struct ofputil_msg_type **typep)
|
||||
{
|
||||
enum { OSM_SIZE = sizeof(struct ofp_stats_msg) };
|
||||
static const struct ofputil_msg_type ofpst_requests[] = {
|
||||
{ OFPUTIL_OFPST_DESC_REQUEST,
|
||||
OFPST_DESC, "OFPST_DESC request",
|
||||
OSM_SIZE, 0 },
|
||||
sizeof(struct ofp_stats_msg), 0 },
|
||||
|
||||
{ OFPUTIL_OFPST_FLOW_REQUEST,
|
||||
OFPST_FLOW, "OFPST_FLOW request",
|
||||
OSM_SIZE + sizeof(struct ofp_flow_stats_request), 0 },
|
||||
sizeof(struct ofp_flow_stats_request), 0 },
|
||||
|
||||
{ OFPUTIL_OFPST_AGGREGATE_REQUEST,
|
||||
OFPST_AGGREGATE, "OFPST_AGGREGATE request",
|
||||
OSM_SIZE + sizeof(struct ofp_flow_stats_request), 0 },
|
||||
sizeof(struct ofp_flow_stats_request), 0 },
|
||||
|
||||
{ OFPUTIL_OFPST_TABLE_REQUEST,
|
||||
OFPST_TABLE, "OFPST_TABLE request",
|
||||
OSM_SIZE, 0 },
|
||||
sizeof(struct ofp_stats_msg), 0 },
|
||||
|
||||
{ OFPUTIL_OFPST_PORT_REQUEST,
|
||||
OFPST_PORT, "OFPST_PORT request",
|
||||
OSM_SIZE + sizeof(struct ofp_port_stats_request), 0 },
|
||||
sizeof(struct ofp_port_stats_request), 0 },
|
||||
|
||||
{ OFPUTIL_OFPST_QUEUE_REQUEST,
|
||||
OFPST_QUEUE, "OFPST_QUEUE request",
|
||||
OSM_SIZE + sizeof(struct ofp_queue_stats_request), 0 },
|
||||
sizeof(struct ofp_queue_stats_request), 0 },
|
||||
|
||||
{ 0,
|
||||
OFPST_VENDOR, "OFPST_VENDOR request",
|
||||
OSM_SIZE + sizeof(uint32_t), 1 },
|
||||
sizeof(struct ofp_vendor_stats_msg), 1 },
|
||||
};
|
||||
|
||||
static const struct ofputil_msg_category ofpst_request_category = {
|
||||
@@ -553,35 +552,34 @@ static int
|
||||
ofputil_decode_ofpst_reply(const struct ofp_header *oh,
|
||||
const struct ofputil_msg_type **typep)
|
||||
{
|
||||
enum { OSM_SIZE = sizeof(struct ofp_stats_msg) };
|
||||
static const struct ofputil_msg_type ofpst_replies[] = {
|
||||
{ OFPUTIL_OFPST_DESC_REPLY,
|
||||
OFPST_DESC, "OFPST_DESC reply",
|
||||
OSM_SIZE + sizeof(struct ofp_desc_stats), 0 },
|
||||
sizeof(struct ofp_desc_stats), 0 },
|
||||
|
||||
{ OFPUTIL_OFPST_FLOW_REPLY,
|
||||
OFPST_FLOW, "OFPST_FLOW reply",
|
||||
OSM_SIZE, 1 },
|
||||
sizeof(struct ofp_stats_msg), 1 },
|
||||
|
||||
{ OFPUTIL_OFPST_AGGREGATE_REPLY,
|
||||
OFPST_AGGREGATE, "OFPST_AGGREGATE reply",
|
||||
OSM_SIZE + sizeof(struct ofp_aggregate_stats_reply), 0 },
|
||||
sizeof(struct ofp_aggregate_stats_reply), 0 },
|
||||
|
||||
{ OFPUTIL_OFPST_TABLE_REPLY,
|
||||
OFPST_TABLE, "OFPST_TABLE reply",
|
||||
OSM_SIZE, sizeof(struct ofp_table_stats) },
|
||||
sizeof(struct ofp_stats_msg), sizeof(struct ofp_table_stats) },
|
||||
|
||||
{ OFPUTIL_OFPST_PORT_REPLY,
|
||||
OFPST_PORT, "OFPST_PORT reply",
|
||||
OSM_SIZE, sizeof(struct ofp_port_stats) },
|
||||
sizeof(struct ofp_stats_msg), sizeof(struct ofp_port_stats) },
|
||||
|
||||
{ OFPUTIL_OFPST_QUEUE_REPLY,
|
||||
OFPST_QUEUE, "OFPST_QUEUE reply",
|
||||
OSM_SIZE, sizeof(struct ofp_queue_stats) },
|
||||
sizeof(struct ofp_stats_msg), sizeof(struct ofp_queue_stats) },
|
||||
|
||||
{ 0,
|
||||
OFPST_VENDOR, "OFPST_VENDOR reply",
|
||||
OSM_SIZE + sizeof(uint32_t), 1 },
|
||||
sizeof(struct ofp_vendor_stats_msg), 1 },
|
||||
};
|
||||
|
||||
static const struct ofputil_msg_category ofpst_reply_category = {
|
||||
@@ -1015,7 +1013,8 @@ ofputil_decode_ofpst_flow_request(struct flow_stats_request *fsr,
|
||||
const struct ofp_header *oh,
|
||||
bool aggregate)
|
||||
{
|
||||
const struct ofp_flow_stats_request *ofsr = ofputil_stats_body(oh);
|
||||
const struct ofp_flow_stats_request *ofsr =
|
||||
(const struct ofp_flow_stats_request *) oh;
|
||||
|
||||
fsr->aggregate = aggregate;
|
||||
ofputil_cls_rule_from_match(&ofsr->match, 0, &fsr->match);
|
||||
@@ -1100,7 +1099,7 @@ ofputil_encode_flow_stats_request(const struct flow_stats_request *fsr,
|
||||
int type;
|
||||
|
||||
type = fsr->aggregate ? OFPST_AGGREGATE : OFPST_FLOW;
|
||||
ofsr = ofputil_make_stats_request(sizeof *ofsr, type, &msg);
|
||||
ofsr = ofputil_make_stats_request(sizeof *ofsr, type, 0, &msg);
|
||||
ofputil_cls_rule_to_match(&fsr->match, &ofsr->match);
|
||||
ofsr->table_id = fsr->table_id;
|
||||
ofsr->out_port = htons(fsr->out_port);
|
||||
@@ -1110,7 +1109,7 @@ ofputil_encode_flow_stats_request(const struct flow_stats_request *fsr,
|
||||
int subtype;
|
||||
|
||||
subtype = fsr->aggregate ? NXST_AGGREGATE : NXST_FLOW;
|
||||
ofputil_make_nxstats_request(sizeof *nfsr, subtype, &msg);
|
||||
ofputil_make_stats_request(sizeof *nfsr, OFPST_VENDOR, subtype, &msg);
|
||||
match_len = nx_put_match(msg, &fsr->match);
|
||||
|
||||
nfsr = msg->data;
|
||||
@@ -1520,34 +1519,130 @@ update_openflow_length(struct ofpbuf *buffer)
|
||||
oh->length = htons(buffer->size);
|
||||
}
|
||||
|
||||
/* Creates an ofp_stats_msg with the given 'type' and 'body_len' bytes of space
|
||||
* allocated following the ofp_stats_msg header. */
|
||||
void *
|
||||
ofputil_make_stats_request(size_t body_len, uint16_t type,
|
||||
struct ofpbuf **bufferp)
|
||||
static void
|
||||
put_stats__(ovs_be32 xid, uint8_t ofp_type,
|
||||
ovs_be16 ofpst_type, ovs_be32 nxst_subtype,
|
||||
struct ofpbuf *msg)
|
||||
{
|
||||
struct ofp_stats_msg *request;
|
||||
request = make_openflow(sizeof *request + body_len, OFPT_STATS_REQUEST,
|
||||
bufferp);
|
||||
request->type = htons(type);
|
||||
request->flags = htons(0);
|
||||
return request + 1;
|
||||
if (ofpst_type == htons(OFPST_VENDOR)) {
|
||||
struct nicira_stats_msg *nsm;
|
||||
|
||||
nsm = put_openflow_xid(sizeof *nsm, ofp_type, xid, msg);
|
||||
nsm->vsm.osm.type = ofpst_type;
|
||||
nsm->vsm.vendor = htonl(NX_VENDOR_ID);
|
||||
nsm->subtype = nxst_subtype;
|
||||
} else {
|
||||
struct ofp_stats_msg *osm;
|
||||
|
||||
osm = put_openflow_xid(sizeof *osm, ofp_type, xid, msg);
|
||||
osm->type = ofpst_type;
|
||||
}
|
||||
}
|
||||
|
||||
/* Creates a stats request message with Nicira as vendor and the given
|
||||
* 'subtype', of total length 'openflow_len'. Returns the message. */
|
||||
/* Creates a statistics request message with total length 'openflow_len'
|
||||
* (including all headers) and the given 'ofpst_type', and stores the buffer
|
||||
* containing the new message in '*bufferp'. If 'ofpst_type' is OFPST_VENDOR
|
||||
* then 'nxst_subtype' is used as the Nicira vendor extension statistics
|
||||
* subtype (otherwise 'nxst_subtype' is ignored).
|
||||
*
|
||||
* Initializes bytes following the headers to all-bits-zero.
|
||||
*
|
||||
* Returns the first byte of the new message. */
|
||||
void *
|
||||
ofputil_make_nxstats_request(size_t openflow_len, uint32_t subtype,
|
||||
struct ofpbuf **bufferp)
|
||||
ofputil_make_stats_request(size_t openflow_len, uint16_t ofpst_type,
|
||||
uint32_t nxst_subtype, struct ofpbuf **bufferp)
|
||||
{
|
||||
struct nicira_stats_msg *nsm;
|
||||
struct ofpbuf *msg;
|
||||
|
||||
nsm = make_openflow(openflow_len, OFPT_STATS_REQUEST, bufferp);
|
||||
nsm->type = htons(OFPST_VENDOR);
|
||||
nsm->flags = htons(0);
|
||||
nsm->vendor = htonl(NX_VENDOR_ID);
|
||||
nsm->subtype = htonl(subtype);
|
||||
return nsm;
|
||||
msg = *bufferp = ofpbuf_new(openflow_len);
|
||||
put_stats__(alloc_xid(), OFPT_STATS_REQUEST,
|
||||
htons(ofpst_type), htonl(nxst_subtype), msg);
|
||||
ofpbuf_padto(msg, openflow_len);
|
||||
|
||||
return msg->data;
|
||||
}
|
||||
|
||||
static void
|
||||
put_stats_reply__(const struct ofp_stats_msg *request, struct ofpbuf *msg)
|
||||
{
|
||||
assert(request->header.type == OFPT_STATS_REQUEST ||
|
||||
request->header.type == OFPT_STATS_REPLY);
|
||||
put_stats__(request->header.xid, OFPT_STATS_REPLY, request->type,
|
||||
(request->type != htons(OFPST_VENDOR)
|
||||
? htonl(0)
|
||||
: ((const struct nicira_stats_msg *) request)->subtype),
|
||||
msg);
|
||||
}
|
||||
|
||||
/* Creates a statistics reply message with total length 'openflow_len'
|
||||
* (including all headers) and the same type (either a standard OpenFlow
|
||||
* statistics type or a Nicira extension type and subtype) as 'request', and
|
||||
* stores the buffer containing the new message in '*bufferp'.
|
||||
*
|
||||
* Initializes bytes following the headers to all-bits-zero.
|
||||
*
|
||||
* Returns the first byte of the new message. */
|
||||
void *
|
||||
ofputil_make_stats_reply(size_t openflow_len,
|
||||
const struct ofp_stats_msg *request,
|
||||
struct ofpbuf **bufferp)
|
||||
{
|
||||
struct ofpbuf *msg;
|
||||
|
||||
msg = *bufferp = ofpbuf_new(openflow_len);
|
||||
put_stats_reply__(request, msg);
|
||||
ofpbuf_padto(msg, openflow_len);
|
||||
|
||||
return msg->data;
|
||||
}
|
||||
|
||||
/* Initializes 'replies' as a list of ofpbufs that will contain a series of
|
||||
* replies to 'request', which should be an OpenFlow or Nicira extension
|
||||
* statistics request. Initially 'replies' will have a single reply message
|
||||
* that has only a header. The functions ofputil_reserve_stats_reply() and
|
||||
* ofputil_append_stats_reply() may be used to add to the reply. */
|
||||
void
|
||||
ofputil_start_stats_reply(const struct ofp_stats_msg *request,
|
||||
struct list *replies)
|
||||
{
|
||||
struct ofpbuf *msg;
|
||||
|
||||
msg = ofpbuf_new(1024);
|
||||
put_stats_reply__(request, msg);
|
||||
|
||||
list_init(replies);
|
||||
list_push_back(replies, &msg->list_node);
|
||||
}
|
||||
|
||||
/* Prepares to append up to 'len' bytes to the series of statistics replies in
|
||||
* 'replies', which should have been initialized with
|
||||
* ofputil_start_stats_reply(). Returns an ofpbuf with at least 'len' bytes of
|
||||
* tailroom. (The 'len' bytes have not actually be allocated; the caller must
|
||||
* do so with e.g. ofpbuf_put_uninit().) */
|
||||
struct ofpbuf *
|
||||
ofputil_reserve_stats_reply(size_t len, struct list *replies)
|
||||
{
|
||||
struct ofpbuf *msg = ofpbuf_from_list(list_back(replies));
|
||||
struct ofp_stats_msg *osm = msg->data;
|
||||
|
||||
if (msg->size + len <= UINT16_MAX) {
|
||||
ofpbuf_prealloc_tailroom(msg, len);
|
||||
} else {
|
||||
osm->flags |= htons(OFPSF_REPLY_MORE);
|
||||
|
||||
msg = ofpbuf_new(MAX(1024, sizeof(struct nicira_stats_msg) + len));
|
||||
put_stats_reply__(osm, msg);
|
||||
list_push_back(replies, &msg->list_node);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/* Appends 'len' bytes to the series of statistics replies in 'replies', and
|
||||
* returns the first byte. */
|
||||
void *
|
||||
ofputil_append_stats_reply(size_t len, struct list *replies)
|
||||
{
|
||||
return ofpbuf_put_uninit(ofputil_reserve_stats_reply(len, replies), len);
|
||||
}
|
||||
|
||||
/* Returns the first byte past the ofp_stats_msg header in 'oh'. */
|
||||
|
@@ -221,10 +221,16 @@ void *put_nxmsg_xid(size_t openflow_len, uint32_t subtype, ovs_be32 xid,
|
||||
|
||||
void update_openflow_length(struct ofpbuf *);
|
||||
|
||||
void *ofputil_make_stats_request(size_t body_len, uint16_t type,
|
||||
struct ofpbuf **);
|
||||
void *ofputil_make_nxstats_request(size_t openflow_len, uint32_t subtype,
|
||||
struct ofpbuf **);
|
||||
void *ofputil_make_stats_request(size_t openflow_len, uint16_t type,
|
||||
uint32_t subtype, struct ofpbuf **);
|
||||
void *ofputil_make_stats_reply(size_t openflow_len,
|
||||
const struct ofp_stats_msg *request,
|
||||
struct ofpbuf **);
|
||||
|
||||
void ofputil_start_stats_reply(const struct ofp_stats_msg *request,
|
||||
struct list *);
|
||||
struct ofpbuf *ofputil_reserve_stats_reply(size_t len, struct list *);
|
||||
void *ofputil_append_stats_reply(size_t len, struct list *);
|
||||
|
||||
const void *ofputil_stats_body(const struct ofp_header *);
|
||||
size_t ofputil_stats_body_len(const struct ofp_header *);
|
||||
|
10
lib/ofpbuf.c
10
lib/ofpbuf.c
@@ -289,6 +289,16 @@ ofpbuf_trim(struct ofpbuf *b)
|
||||
}
|
||||
}
|
||||
|
||||
/* If 'b' is shorter than 'length' bytes, pads its tail out with zeros to that
|
||||
* length. */
|
||||
void
|
||||
ofpbuf_padto(struct ofpbuf *b, size_t length)
|
||||
{
|
||||
if (b->size < length) {
|
||||
ofpbuf_put_zeros(b, length - b->size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
|
||||
* copying its data if necessary. Returns a pointer to the first byte of the
|
||||
* new data, which is left uninitialized. */
|
||||
|
@@ -91,6 +91,7 @@ size_t ofpbuf_tailroom(const struct ofpbuf *);
|
||||
void ofpbuf_prealloc_headroom(struct ofpbuf *, size_t);
|
||||
void ofpbuf_prealloc_tailroom(struct ofpbuf *, size_t);
|
||||
void ofpbuf_trim(struct ofpbuf *);
|
||||
void ofpbuf_padto(struct ofpbuf *, size_t);
|
||||
|
||||
void ofpbuf_clear(struct ofpbuf *);
|
||||
void *ofpbuf_pull(struct ofpbuf *, size_t);
|
||||
|
@@ -765,6 +765,19 @@ ofconn_send_reply(const struct ofconn *ofconn, struct ofpbuf *msg)
|
||||
ofconn_send(ofconn, msg, ofconn->reply_counter);
|
||||
}
|
||||
|
||||
/* Sends each of the messages in list 'replies' on 'ofconn' in order,
|
||||
* accounting them as replies. */
|
||||
void
|
||||
ofconn_send_replies(const struct ofconn *ofconn, struct list *replies)
|
||||
{
|
||||
struct ofpbuf *reply, *next;
|
||||
|
||||
LIST_FOR_EACH_SAFE (reply, next, list_node, replies) {
|
||||
list_remove(&reply->list_node);
|
||||
ofconn_send_reply(ofconn, reply);
|
||||
}
|
||||
}
|
||||
|
||||
/* Same as pktbuf_retrieve(), using the pktbuf owned by 'ofconn'. */
|
||||
int
|
||||
ofconn_pktbuf_retrieve(struct ofconn *ofconn, uint32_t id,
|
||||
|
@@ -87,6 +87,7 @@ int ofconn_get_miss_send_len(const struct ofconn *);
|
||||
void ofconn_set_miss_send_len(struct ofconn *, int miss_send_len);
|
||||
|
||||
void ofconn_send_reply(const struct ofconn *, struct ofpbuf *);
|
||||
void ofconn_send_replies(const struct ofconn *, struct list *);
|
||||
|
||||
int ofconn_pktbuf_retrieve(struct ofconn *, uint32_t id,
|
||||
struct ofpbuf **bufferp, uint16_t *in_port);
|
||||
|
@@ -1582,88 +1582,15 @@ handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ofpbuf *
|
||||
make_ofp_stats_reply(ovs_be32 xid, ovs_be16 type, size_t body_len)
|
||||
{
|
||||
struct ofp_stats_msg *reply;
|
||||
struct ofpbuf *msg;
|
||||
|
||||
msg = ofpbuf_new(MIN(sizeof *reply + body_len, UINT16_MAX));
|
||||
reply = put_openflow_xid(sizeof *reply, OFPT_STATS_REPLY, xid, msg);
|
||||
reply->type = type;
|
||||
reply->flags = htons(0);
|
||||
return msg;
|
||||
}
|
||||
|
||||
static struct ofpbuf *
|
||||
start_ofp_stats_reply(const struct ofp_header *request, size_t body_len)
|
||||
{
|
||||
const struct ofp_stats_msg *osm = (const struct ofp_stats_msg *) request;
|
||||
return make_ofp_stats_reply(osm->header.xid, osm->type, body_len);
|
||||
}
|
||||
|
||||
static void *
|
||||
append_ofp_stats_reply(size_t nbytes, struct ofconn *ofconn,
|
||||
struct ofpbuf **msgp)
|
||||
{
|
||||
struct ofpbuf *msg = *msgp;
|
||||
assert(nbytes <= UINT16_MAX - sizeof(struct ofp_stats_msg));
|
||||
if (nbytes + msg->size > UINT16_MAX) {
|
||||
struct ofp_stats_msg *reply = msg->data;
|
||||
reply->flags = htons(OFPSF_REPLY_MORE);
|
||||
*msgp = make_ofp_stats_reply(reply->header.xid, reply->type, nbytes);
|
||||
ofconn_send_reply(ofconn, msg);
|
||||
}
|
||||
return ofpbuf_put_uninit(*msgp, nbytes);
|
||||
}
|
||||
|
||||
static struct ofpbuf *
|
||||
make_nxstats_reply(ovs_be32 xid, ovs_be32 subtype, size_t body_len)
|
||||
{
|
||||
struct nicira_stats_msg *nsm;
|
||||
struct ofpbuf *msg;
|
||||
|
||||
msg = ofpbuf_new(MIN(sizeof *nsm + body_len, UINT16_MAX));
|
||||
nsm = put_openflow_xid(sizeof *nsm, OFPT_STATS_REPLY, xid, msg);
|
||||
nsm->type = htons(OFPST_VENDOR);
|
||||
nsm->flags = htons(0);
|
||||
nsm->vendor = htonl(NX_VENDOR_ID);
|
||||
nsm->subtype = subtype;
|
||||
return msg;
|
||||
}
|
||||
|
||||
static struct ofpbuf *
|
||||
start_nxstats_reply(const struct nicira_stats_msg *request, size_t body_len)
|
||||
{
|
||||
return make_nxstats_reply(request->header.xid, request->subtype, body_len);
|
||||
}
|
||||
|
||||
static void
|
||||
append_nxstats_reply(size_t nbytes, struct ofconn *ofconn,
|
||||
struct ofpbuf **msgp)
|
||||
{
|
||||
struct ofpbuf *msg = *msgp;
|
||||
assert(nbytes <= UINT16_MAX - sizeof(struct nicira_stats_msg));
|
||||
if (nbytes + msg->size > UINT16_MAX) {
|
||||
struct nicira_stats_msg *reply = msg->data;
|
||||
reply->flags = htons(OFPSF_REPLY_MORE);
|
||||
*msgp = make_nxstats_reply(reply->header.xid, reply->subtype, nbytes);
|
||||
ofconn_send_reply(ofconn, msg);
|
||||
}
|
||||
ofpbuf_prealloc_tailroom(*msgp, nbytes);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_desc_stats_request(struct ofconn *ofconn,
|
||||
const struct ofp_header *request)
|
||||
const struct ofp_stats_msg *request)
|
||||
{
|
||||
struct ofproto *p = ofconn_get_ofproto(ofconn);
|
||||
struct ofp_desc_stats *ods;
|
||||
struct ofpbuf *msg;
|
||||
|
||||
msg = start_ofp_stats_reply(request, sizeof *ods);
|
||||
ods = append_ofp_stats_reply(sizeof *ods, ofconn, &msg);
|
||||
memset(ods, 0, sizeof *ods);
|
||||
ods = ofputil_make_stats_reply(sizeof *ods, request, &msg);
|
||||
ovs_strlcpy(ods->mfr_desc, p->mfr_desc, sizeof ods->mfr_desc);
|
||||
ovs_strlcpy(ods->hw_desc, p->hw_desc, sizeof ods->hw_desc);
|
||||
ovs_strlcpy(ods->sw_desc, p->sw_desc, sizeof ods->sw_desc);
|
||||
@@ -1676,14 +1603,14 @@ handle_desc_stats_request(struct ofconn *ofconn,
|
||||
|
||||
static int
|
||||
handle_table_stats_request(struct ofconn *ofconn,
|
||||
const struct ofp_header *request)
|
||||
const struct ofp_stats_msg *request)
|
||||
{
|
||||
struct ofproto *p = ofconn_get_ofproto(ofconn);
|
||||
struct ofp_table_stats *ots;
|
||||
struct ofpbuf *msg;
|
||||
size_t i;
|
||||
|
||||
msg = start_ofp_stats_reply(request, sizeof *ots * p->n_tables);
|
||||
ofputil_make_stats_reply(sizeof(struct ofp_stats_msg), request, &msg);
|
||||
|
||||
ots = ofpbuf_put_zeros(msg, sizeof *ots * p->n_tables);
|
||||
for (i = 0; i < p->n_tables; i++) {
|
||||
@@ -1701,8 +1628,7 @@ handle_table_stats_request(struct ofconn *ofconn,
|
||||
}
|
||||
|
||||
static void
|
||||
append_port_stat(struct ofport *port, struct ofconn *ofconn,
|
||||
struct ofpbuf **msgp)
|
||||
append_port_stat(struct ofport *port, struct list *replies)
|
||||
{
|
||||
struct netdev_stats stats;
|
||||
struct ofp_port_stats *ops;
|
||||
@@ -1712,7 +1638,7 @@ append_port_stat(struct ofport *port, struct ofconn *ofconn,
|
||||
* netdev_get_stats() will log errors. */
|
||||
netdev_get_stats(port->netdev, &stats);
|
||||
|
||||
ops = append_ofp_stats_reply(sizeof *ops, ofconn, msgp);
|
||||
ops = ofputil_append_stats_reply(sizeof *ops, replies);
|
||||
ops->port_no = port->opp.port_no;
|
||||
memset(ops->pad, 0, sizeof ops->pad);
|
||||
put_32aligned_be64(&ops->rx_packets, htonll(stats.rx_packets));
|
||||
@@ -1730,27 +1656,26 @@ append_port_stat(struct ofport *port, struct ofconn *ofconn,
|
||||
}
|
||||
|
||||
static int
|
||||
handle_port_stats_request(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
handle_port_stats_request(struct ofconn *ofconn,
|
||||
const struct ofp_port_stats_request *psr)
|
||||
{
|
||||
struct ofproto *p = ofconn_get_ofproto(ofconn);
|
||||
const struct ofp_port_stats_request *psr = ofputil_stats_body(oh);
|
||||
struct ofp_port_stats *ops;
|
||||
struct ofpbuf *msg;
|
||||
struct ofport *port;
|
||||
struct list replies;
|
||||
|
||||
msg = start_ofp_stats_reply(oh, sizeof *ops * 16);
|
||||
ofputil_start_stats_reply(&psr->osm, &replies);
|
||||
if (psr->port_no != htons(OFPP_NONE)) {
|
||||
port = ofproto_get_port(p, ntohs(psr->port_no));
|
||||
if (port) {
|
||||
append_port_stat(port, ofconn, &msg);
|
||||
append_port_stat(port, &replies);
|
||||
}
|
||||
} else {
|
||||
HMAP_FOR_EACH (port, hmap_node, &p->ports) {
|
||||
append_port_stat(port, ofconn, &msg);
|
||||
append_port_stat(port, &replies);
|
||||
}
|
||||
}
|
||||
|
||||
ofconn_send_reply(ofconn, msg);
|
||||
ofconn_send_replies(ofconn, &replies);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1774,7 +1699,7 @@ calc_flow_duration(long long int start, ovs_be32 *sec_be, ovs_be32 *nsec_be)
|
||||
|
||||
static void
|
||||
put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule,
|
||||
ovs_be16 out_port, struct ofpbuf **replyp)
|
||||
ovs_be16 out_port, struct list *replies)
|
||||
{
|
||||
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
|
||||
struct ofp_flow_stats *ofs;
|
||||
@@ -1790,7 +1715,7 @@ put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule,
|
||||
|
||||
ofproto->ofproto_class->rule_get_stats(rule, &packet_count, &byte_count);
|
||||
|
||||
ofs = append_ofp_stats_reply(len, ofconn, replyp);
|
||||
ofs = ofputil_append_stats_reply(len, replies);
|
||||
ofs->length = htons(len);
|
||||
ofs->table_id = rule->table_id;
|
||||
ofs->pad = 0;
|
||||
@@ -1854,16 +1779,16 @@ next_matching_table(struct ofproto *ofproto,
|
||||
(CLS) = next_matching_table(OFPROTO, CLS, TABLE_ID))
|
||||
|
||||
static int
|
||||
handle_flow_stats_request(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
handle_flow_stats_request(struct ofconn *ofconn,
|
||||
const struct ofp_flow_stats_request *fsr)
|
||||
{
|
||||
const struct ofp_flow_stats_request *fsr = ofputil_stats_body(oh);
|
||||
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
|
||||
struct classifier *cls;
|
||||
struct cls_rule target;
|
||||
struct ofpbuf *reply;
|
||||
struct list replies;
|
||||
|
||||
COVERAGE_INC(ofproto_flows_req);
|
||||
reply = start_ofp_stats_reply(oh, 1024);
|
||||
ofputil_start_stats_reply(&fsr->osm, &replies);
|
||||
ofputil_cls_rule_from_match(&fsr->match, 0, &target);
|
||||
FOR_EACH_MATCHING_TABLE (cls, fsr->table_id, ofproto) {
|
||||
struct cls_cursor cursor;
|
||||
@@ -1871,17 +1796,16 @@ handle_flow_stats_request(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
|
||||
cls_cursor_init(&cursor, cls, &target);
|
||||
CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
|
||||
put_ofp_flow_stats(ofconn, rule, fsr->out_port, &reply);
|
||||
put_ofp_flow_stats(ofconn, rule, fsr->out_port, &replies);
|
||||
}
|
||||
}
|
||||
ofconn_send_reply(ofconn, reply);
|
||||
ofconn_send_replies(ofconn, &replies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
put_nx_flow_stats(struct ofconn *ofconn, struct rule *rule,
|
||||
ovs_be16 out_port, struct ofpbuf **replyp)
|
||||
put_nx_flow_stats(struct rule *rule, ovs_be16 out_port, struct list *replies)
|
||||
{
|
||||
struct nx_flow_stats *nfs;
|
||||
uint64_t packet_count, byte_count;
|
||||
@@ -1897,9 +1821,9 @@ put_nx_flow_stats(struct ofconn *ofconn, struct rule *rule,
|
||||
|
||||
act_len = sizeof *rule->actions * rule->n_actions;
|
||||
|
||||
append_nxstats_reply(sizeof *nfs + NXM_MAX_LEN + act_len, ofconn, replyp);
|
||||
start_len = (*replyp)->size;
|
||||
reply = *replyp;
|
||||
reply = ofputil_reserve_stats_reply(sizeof *nfs + NXM_MAX_LEN + act_len,
|
||||
replies);
|
||||
start_len = reply->size;
|
||||
|
||||
nfs = ofpbuf_put_uninit(reply, sizeof *nfs);
|
||||
nfs->table_id = rule->table_id;
|
||||
@@ -1920,17 +1844,17 @@ put_nx_flow_stats(struct ofconn *ofconn, struct rule *rule,
|
||||
}
|
||||
|
||||
static int
|
||||
handle_nxst_flow(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
handle_nxst_flow(struct ofconn *ofconn, const struct ofp_stats_msg *osm)
|
||||
{
|
||||
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
|
||||
struct nx_flow_stats_request *nfsr;
|
||||
struct classifier *cls;
|
||||
struct cls_rule target;
|
||||
struct ofpbuf *reply;
|
||||
struct list replies;
|
||||
struct ofpbuf b;
|
||||
int error;
|
||||
|
||||
ofpbuf_use_const(&b, oh, ntohs(oh->length));
|
||||
ofpbuf_use_const(&b, osm, ntohs(osm->header.length));
|
||||
|
||||
/* Dissect the message. */
|
||||
nfsr = ofpbuf_pull(&b, sizeof *nfsr);
|
||||
@@ -1943,17 +1867,17 @@ handle_nxst_flow(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
}
|
||||
|
||||
COVERAGE_INC(ofproto_flows_req);
|
||||
reply = start_nxstats_reply(&nfsr->nsm, 1024);
|
||||
ofputil_start_stats_reply(osm, &replies);
|
||||
FOR_EACH_MATCHING_TABLE (cls, nfsr->table_id, ofproto) {
|
||||
struct cls_cursor cursor;
|
||||
struct rule *rule;
|
||||
|
||||
cls_cursor_init(&cursor, cls, &target);
|
||||
CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
|
||||
put_nx_flow_stats(ofconn, rule, nfsr->out_port, &reply);
|
||||
put_nx_flow_stats(rule, nfsr->out_port, &replies);
|
||||
}
|
||||
}
|
||||
ofconn_send_reply(ofconn, reply);
|
||||
ofconn_send_replies(ofconn, &replies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2064,9 +1988,8 @@ query_aggregate_stats(struct ofproto *ofproto, struct cls_rule *target,
|
||||
|
||||
static int
|
||||
handle_aggregate_stats_request(struct ofconn *ofconn,
|
||||
const struct ofp_header *oh)
|
||||
const struct ofp_flow_stats_request *request)
|
||||
{
|
||||
const struct ofp_flow_stats_request *request = ofputil_stats_body(oh);
|
||||
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
|
||||
struct ofp_aggregate_stats_reply *reply;
|
||||
uint64_t total_packets, total_bytes;
|
||||
@@ -2075,13 +1998,11 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
|
||||
uint32_t n_flows;
|
||||
|
||||
ofputil_cls_rule_from_match(&request->match, 0, &target);
|
||||
|
||||
msg = start_ofp_stats_reply(oh, sizeof *reply);
|
||||
reply = append_ofp_stats_reply(sizeof *reply, ofconn, &msg);
|
||||
query_aggregate_stats(ofproto, &target, request->out_port,
|
||||
request->table_id,
|
||||
&total_packets, &total_bytes, &n_flows);
|
||||
|
||||
reply = ofputil_make_stats_reply(sizeof *reply, &request->osm, &msg);
|
||||
reply->flow_count = htonl(n_flows);
|
||||
put_32aligned_be64(&reply->packet_count, htonll(total_packets));
|
||||
put_32aligned_be64(&reply->byte_count, htonll(total_bytes));
|
||||
@@ -2101,12 +2022,12 @@ handle_nxst_aggregate(struct ofconn *ofconn,
|
||||
struct nx_aggregate_stats_reply *reply;
|
||||
uint64_t total_packets, total_bytes;
|
||||
struct cls_rule target;
|
||||
struct ofpbuf b;
|
||||
struct ofpbuf *buf;
|
||||
struct ofpbuf *msg;
|
||||
uint32_t n_flows;
|
||||
struct ofpbuf b;
|
||||
int error;
|
||||
|
||||
ofpbuf_use_const(&b, nasr, ntohs(nasr->nsm.header.length));
|
||||
ofpbuf_use_const(&b, nasr, ntohs(nasr->nsm.vsm.osm.header.length));
|
||||
|
||||
/* Dissect the message. */
|
||||
request = ofpbuf_pull(&b, sizeof *request);
|
||||
@@ -2125,21 +2046,20 @@ handle_nxst_aggregate(struct ofconn *ofconn,
|
||||
|
||||
/* Reply. */
|
||||
COVERAGE_INC(ofproto_flows_req);
|
||||
buf = start_nxstats_reply(&request->nsm, sizeof *reply);
|
||||
reply = ofpbuf_put_uninit(buf, sizeof *reply);
|
||||
reply = ofputil_make_stats_reply(sizeof *reply, &request->nsm.vsm.osm,
|
||||
&msg);
|
||||
reply->flow_count = htonl(n_flows);
|
||||
reply->packet_count = htonll(total_packets);
|
||||
reply->byte_count = htonll(total_bytes);
|
||||
memset(reply->pad, 0, sizeof reply->pad);
|
||||
ofconn_send_reply(ofconn, buf);
|
||||
ofconn_send_reply(ofconn, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct queue_stats_cbdata {
|
||||
struct ofconn *ofconn;
|
||||
struct ofport *ofport;
|
||||
struct ofpbuf *msg;
|
||||
struct list replies;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -2148,7 +2068,7 @@ put_queue_stats(struct queue_stats_cbdata *cbdata, uint32_t queue_id,
|
||||
{
|
||||
struct ofp_queue_stats *reply;
|
||||
|
||||
reply = append_ofp_stats_reply(sizeof *reply, cbdata->ofconn, &cbdata->msg);
|
||||
reply = ofputil_append_stats_reply(sizeof *reply, &cbdata->replies);
|
||||
reply->port_no = cbdata->ofport->opp.port_no;
|
||||
memset(reply->pad, 0, sizeof reply->pad);
|
||||
reply->queue_id = htonl(queue_id);
|
||||
@@ -2185,24 +2105,18 @@ handle_queue_stats_for_port(struct ofport *port, uint32_t queue_id,
|
||||
}
|
||||
|
||||
static int
|
||||
handle_queue_stats_request(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
handle_queue_stats_request(struct ofconn *ofconn,
|
||||
const struct ofp_queue_stats_request *qsr)
|
||||
{
|
||||
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
|
||||
const struct ofp_queue_stats_request *qsr;
|
||||
struct queue_stats_cbdata cbdata;
|
||||
struct ofport *port;
|
||||
unsigned int port_no;
|
||||
uint32_t queue_id;
|
||||
|
||||
qsr = ofputil_stats_body(oh);
|
||||
if (!qsr) {
|
||||
return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
|
||||
}
|
||||
|
||||
COVERAGE_INC(ofproto_queue_req);
|
||||
|
||||
cbdata.ofconn = ofconn;
|
||||
cbdata.msg = start_ofp_stats_reply(oh, 128);
|
||||
ofputil_start_stats_reply(&qsr->osm, &cbdata.replies);
|
||||
|
||||
port_no = ntohs(qsr->port_no);
|
||||
queue_id = ntohl(qsr->queue_id);
|
||||
@@ -2216,10 +2130,10 @@ handle_queue_stats_request(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
handle_queue_stats_for_port(port, queue_id, &cbdata);
|
||||
}
|
||||
} else {
|
||||
ofpbuf_delete(cbdata.msg);
|
||||
ofpbuf_list_delete(&cbdata.replies);
|
||||
return ofp_mkerr(OFPET_QUEUE_OP_FAILED, OFPQOFC_BAD_PORT);
|
||||
}
|
||||
ofconn_send_reply(ofconn, cbdata.msg);
|
||||
ofconn_send_replies(ofconn, &cbdata.replies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2708,26 +2622,26 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
|
||||
|
||||
/* OpenFlow statistics requests. */
|
||||
case OFPUTIL_OFPST_DESC_REQUEST:
|
||||
return handle_desc_stats_request(ofconn, oh);
|
||||
return handle_desc_stats_request(ofconn, msg->data);
|
||||
|
||||
case OFPUTIL_OFPST_FLOW_REQUEST:
|
||||
return handle_flow_stats_request(ofconn, oh);
|
||||
return handle_flow_stats_request(ofconn, msg->data);
|
||||
|
||||
case OFPUTIL_OFPST_AGGREGATE_REQUEST:
|
||||
return handle_aggregate_stats_request(ofconn, oh);
|
||||
return handle_aggregate_stats_request(ofconn, msg->data);
|
||||
|
||||
case OFPUTIL_OFPST_TABLE_REQUEST:
|
||||
return handle_table_stats_request(ofconn, oh);
|
||||
return handle_table_stats_request(ofconn, msg->data);
|
||||
|
||||
case OFPUTIL_OFPST_PORT_REQUEST:
|
||||
return handle_port_stats_request(ofconn, oh);
|
||||
return handle_port_stats_request(ofconn, msg->data);
|
||||
|
||||
case OFPUTIL_OFPST_QUEUE_REQUEST:
|
||||
return handle_queue_stats_request(ofconn, oh);
|
||||
return handle_queue_stats_request(ofconn, msg->data);
|
||||
|
||||
/* Nicira extension statistics requests. */
|
||||
case OFPUTIL_NXST_FLOW_REQUEST:
|
||||
return handle_nxst_flow(ofconn, oh);
|
||||
return handle_nxst_flow(ofconn, msg->data);
|
||||
|
||||
case OFPUTIL_NXST_AGGREGATE_REQUEST:
|
||||
return handle_nxst_aggregate(ofconn, msg->data);
|
||||
|
Reference in New Issue
Block a user