2 * Copyright (c) 2008-2017 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "openvswitch/ofp-queue.h"
19 #include "byte-order.h"
21 #include "openvswitch/ofp-msgs.h"
22 #include "openvswitch/ofp-print.h"
23 #include "openvswitch/ofp-port.h"
24 #include "openvswitch/ofp-prop.h"
25 #include "openvswitch/ofpbuf.h"
26 #include "openvswitch/vlog.h"
29 VLOG_DEFINE_THIS_MODULE(ofp_queue
);
31 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 5);
34 ofp_print_queue_name(struct ds
*string
, uint32_t queue_id
)
36 if (queue_id
== OFPQ_ALL
) {
37 ds_put_cstr(string
, "ALL");
39 ds_put_format(string
, "%"PRIu32
, queue_id
);
43 /* OFPT_QUEUE_GET_CONFIG request and reply. */
45 /* Constructs and returns an OFPT_QUEUE_GET_CONFIG request for the specified
46 * 'port' and 'queue', suitable for OpenFlow version 'version'.
48 * 'queue' is honored only for OpenFlow 1.4 and later; older versions always
49 * request all queues. */
51 ofputil_encode_queue_get_config_request(enum ofp_version version
,
55 struct ofpbuf
*request
;
57 if (version
== OFP10_VERSION
) {
58 struct ofp10_queue_get_config_request
*qgcr10
;
60 request
= ofpraw_alloc(OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST
,
62 qgcr10
= ofpbuf_put_zeros(request
, sizeof *qgcr10
);
63 qgcr10
->port
= htons(ofp_to_u16(port
));
64 } else if (version
< OFP14_VERSION
) {
65 struct ofp11_queue_get_config_request
*qgcr11
;
67 request
= ofpraw_alloc(OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST
,
69 qgcr11
= ofpbuf_put_zeros(request
, sizeof *qgcr11
);
70 qgcr11
->port
= ofputil_port_to_ofp11(port
);
72 struct ofp14_queue_desc_request
*qdr14
;
74 request
= ofpraw_alloc(OFPRAW_OFPST14_QUEUE_DESC_REQUEST
,
76 qdr14
= ofpbuf_put_zeros(request
, sizeof *qdr14
);
77 qdr14
->port
= ofputil_port_to_ofp11(port
);
78 qdr14
->queue
= htonl(queue
);
84 /* Parses OFPT_QUEUE_GET_CONFIG request 'oh', storing the port specified by the
85 * request into '*port'. Returns 0 if successful, otherwise an OpenFlow error
88 ofputil_decode_queue_get_config_request(const struct ofp_header
*oh
,
89 ofp_port_t
*port
, uint32_t *queue
)
91 const struct ofp10_queue_get_config_request
*qgcr10
;
92 const struct ofp11_queue_get_config_request
*qgcr11
;
93 const struct ofp14_queue_desc_request
*qdr14
;
94 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
95 enum ofpraw raw
= ofpraw_pull_assert(&b
);
98 case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST
:
100 *port
= u16_to_ofp(ntohs(qgcr10
->port
));
104 case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST
:
107 enum ofperr error
= ofputil_port_from_ofp11(qgcr11
->port
, port
);
108 if (error
|| *port
== OFPP_ANY
) {
113 case OFPRAW_OFPST14_QUEUE_DESC_REQUEST
:
115 *queue
= ntohl(qdr14
->queue
);
116 return ofputil_port_from_ofp11(qdr14
->port
, port
);
122 return (ofp_to_u16(*port
) < ofp_to_u16(OFPP_MAX
)
124 : OFPERR_OFPQOFC_BAD_PORT
);
128 ofputil_queue_get_config_request_format(
129 struct ds
*string
, const struct ofp_header
*oh
,
130 const struct ofputil_port_map
*port_map
)
136 error
= ofputil_decode_queue_get_config_request(oh
, &port
, &queue
);
141 ds_put_cstr(string
, " port=");
142 ofputil_format_port(port
, port_map
, string
);
144 if (queue
!= OFPQ_ALL
) {
145 ds_put_cstr(string
, " queue=");
146 ofp_print_queue_name(string
, queue
);
152 /* Constructs and returns the beginning of a reply to
153 * OFPT_QUEUE_GET_CONFIG_REQUEST or OFPMP_QUEUE_DESC request 'oh'. The caller
154 * may append information about individual queues with
155 * ofputil_append_queue_get_config_reply(). */
157 ofputil_start_queue_get_config_reply(const struct ofp_header
*request
,
158 struct ovs_list
*replies
)
160 struct ofpbuf
*reply
;
164 ovs_assert(!ofputil_decode_queue_get_config_request(request
, &port
,
167 enum ofpraw raw
= ofpraw_decode_assert(request
);
169 case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST
:
170 reply
= ofpraw_alloc_reply(OFPRAW_OFPT10_QUEUE_GET_CONFIG_REPLY
,
172 struct ofp10_queue_get_config_reply
*qgcr10
173 = ofpbuf_put_zeros(reply
, sizeof *qgcr10
);
174 qgcr10
->port
= htons(ofp_to_u16(port
));
177 case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST
:
178 reply
= ofpraw_alloc_reply(OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY
,
180 struct ofp11_queue_get_config_reply
*qgcr11
181 = ofpbuf_put_zeros(reply
, sizeof *qgcr11
);
182 qgcr11
->port
= ofputil_port_to_ofp11(port
);
185 case OFPRAW_OFPST14_QUEUE_DESC_REQUEST
:
186 reply
= ofpraw_alloc_stats_reply(request
, 0);
193 ovs_list_init(replies
);
194 ovs_list_push_back(replies
, &reply
->list_node
);
198 put_ofp10_queue_rate(struct ofpbuf
*reply
,
199 enum ofp10_queue_properties property
, uint16_t rate
)
201 if (rate
!= UINT16_MAX
) {
202 struct ofp10_queue_prop_rate
*oqpr
;
204 oqpr
= ofpbuf_put_zeros(reply
, sizeof *oqpr
);
205 oqpr
->prop_header
.property
= htons(property
);
206 oqpr
->prop_header
.len
= htons(sizeof *oqpr
);
207 oqpr
->rate
= htons(rate
);
212 put_ofp14_queue_rate(struct ofpbuf
*reply
,
213 enum ofp14_queue_desc_prop_type type
, uint16_t rate
)
215 if (rate
!= UINT16_MAX
) {
216 ofpprop_put_u16(reply
, type
, rate
);
221 ofputil_append_queue_get_config_reply(const struct ofputil_queue_config
*qc
,
222 struct ovs_list
*replies
)
224 enum ofp_version ofp_version
= ofpmp_version(replies
);
225 struct ofpbuf
*reply
= ofpbuf_from_list(ovs_list_back(replies
));
226 size_t start_ofs
= reply
->size
;
230 if (ofp_version
< OFP14_VERSION
) {
231 if (ofp_version
< OFP12_VERSION
) {
232 struct ofp10_packet_queue
*opq10
;
234 opq10
= ofpbuf_put_zeros(reply
, sizeof *opq10
);
235 opq10
->queue_id
= htonl(qc
->queue
);
236 len_ofs
= (char *) &opq10
->len
- (char *) reply
->data
;
238 struct ofp12_packet_queue
*opq12
;
240 opq12
= ofpbuf_put_zeros(reply
, sizeof *opq12
);
241 opq12
->port
= ofputil_port_to_ofp11(qc
->port
);
242 opq12
->queue_id
= htonl(qc
->queue
);
243 len_ofs
= (char *) &opq12
->len
- (char *) reply
->data
;
246 put_ofp10_queue_rate(reply
, OFPQT10_MIN_RATE
, qc
->min_rate
);
247 put_ofp10_queue_rate(reply
, OFPQT11_MAX_RATE
, qc
->max_rate
);
249 struct ofp14_queue_desc
*oqd
= ofpbuf_put_zeros(reply
, sizeof *oqd
);
250 oqd
->port_no
= ofputil_port_to_ofp11(qc
->port
);
251 oqd
->queue_id
= htonl(qc
->queue
);
252 len_ofs
= (char *) &oqd
->len
- (char *) reply
->data
;
253 put_ofp14_queue_rate(reply
, OFPQDPT14_MIN_RATE
, qc
->min_rate
);
254 put_ofp14_queue_rate(reply
, OFPQDPT14_MAX_RATE
, qc
->max_rate
);
257 len
= ofpbuf_at(reply
, len_ofs
, sizeof *len
);
258 *len
= htons(reply
->size
- start_ofs
);
260 if (ofp_version
>= OFP14_VERSION
) {
261 ofpmp_postappend(replies
, start_ofs
);
266 parse_ofp10_queue_rate(const struct ofp10_queue_prop_header
*hdr
,
269 const struct ofp10_queue_prop_rate
*oqpr
;
271 if (hdr
->len
== htons(sizeof *oqpr
)) {
272 oqpr
= (const struct ofp10_queue_prop_rate
*) hdr
;
273 *rate
= ntohs(oqpr
->rate
);
276 return OFPERR_OFPBRC_BAD_LEN
;
281 ofputil_pull_queue_get_config_reply10(struct ofpbuf
*msg
,
282 struct ofputil_queue_config
*queue
)
284 const struct ofp_header
*oh
= msg
->header
;
285 unsigned int opq_len
; /* Length of protocol-specific queue header. */
286 unsigned int len
; /* Total length of queue + properties. */
288 /* Obtain the port number from the message header. */
289 if (oh
->version
== OFP10_VERSION
) {
290 const struct ofp10_queue_get_config_reply
*oqgcr10
= msg
->msg
;
291 queue
->port
= u16_to_ofp(ntohs(oqgcr10
->port
));
293 const struct ofp11_queue_get_config_reply
*oqgcr11
= msg
->msg
;
294 enum ofperr error
= ofputil_port_from_ofp11(oqgcr11
->port
,
301 /* Pull off the queue header and get the queue number and length. */
302 if (oh
->version
< OFP12_VERSION
) {
303 const struct ofp10_packet_queue
*opq10
;
304 opq10
= ofpbuf_try_pull(msg
, sizeof *opq10
);
306 return OFPERR_OFPBRC_BAD_LEN
;
308 queue
->queue
= ntohl(opq10
->queue_id
);
309 len
= ntohs(opq10
->len
);
310 opq_len
= sizeof *opq10
;
312 const struct ofp12_packet_queue
*opq12
;
313 opq12
= ofpbuf_try_pull(msg
, sizeof *opq12
);
315 return OFPERR_OFPBRC_BAD_LEN
;
317 queue
->queue
= ntohl(opq12
->queue_id
);
318 len
= ntohs(opq12
->len
);
319 opq_len
= sizeof *opq12
;
323 if (len
< opq_len
|| len
> msg
->size
+ opq_len
|| len
% 8) {
324 return OFPERR_OFPBRC_BAD_LEN
;
328 /* Pull properties. The format of these properties differs from used in
329 * OF1.4+ so we can't use the common property functions. */
331 const struct ofp10_queue_prop_header
*hdr
;
332 unsigned int property
;
333 unsigned int prop_len
;
334 enum ofperr error
= 0;
336 hdr
= ofpbuf_at_assert(msg
, 0, sizeof *hdr
);
337 prop_len
= ntohs(hdr
->len
);
338 if (prop_len
< sizeof *hdr
|| prop_len
> len
|| prop_len
% 8) {
339 return OFPERR_OFPBRC_BAD_LEN
;
342 property
= ntohs(hdr
->property
);
344 case OFPQT10_MIN_RATE
:
345 error
= parse_ofp10_queue_rate(hdr
, &queue
->min_rate
);
348 case OFPQT11_MAX_RATE
:
349 error
= parse_ofp10_queue_rate(hdr
, &queue
->max_rate
);
353 VLOG_INFO_RL(&rl
, "unknown queue property %u", property
);
360 ofpbuf_pull(msg
, prop_len
);
367 ofputil_pull_queue_get_config_reply14(struct ofpbuf
*msg
,
368 struct ofputil_queue_config
*queue
)
370 struct ofp14_queue_desc
*oqd14
= ofpbuf_try_pull(msg
, sizeof *oqd14
);
372 return OFPERR_OFPBRC_BAD_LEN
;
374 enum ofperr error
= ofputil_port_from_ofp11(oqd14
->port_no
, &queue
->port
);
378 queue
->queue
= ntohl(oqd14
->queue_id
);
381 unsigned int len
= ntohs(oqd14
->len
);
382 if (len
< sizeof *oqd14
|| len
> msg
->size
+ sizeof *oqd14
|| len
% 8) {
383 return OFPERR_OFPBRC_BAD_LEN
;
385 len
-= sizeof *oqd14
;
387 struct ofpbuf properties
= ofpbuf_const_initializer(ofpbuf_pull(msg
, len
),
389 while (properties
.size
> 0) {
390 struct ofpbuf payload
;
393 error
= ofpprop_pull(&properties
, &payload
, &type
);
399 case OFPQDPT14_MIN_RATE
:
400 error
= ofpprop_parse_u16(&payload
, &queue
->min_rate
);
403 case OFPQDPT14_MAX_RATE
:
404 error
= ofpprop_parse_u16(&payload
, &queue
->max_rate
);
408 error
= OFPPROP_UNKNOWN(true, "queue desc", type
);
420 /* Decodes information about a queue from the OFPT_QUEUE_GET_CONFIG_REPLY in
421 * 'reply' and stores it in '*queue'. ofputil_decode_queue_get_config_reply()
422 * must already have pulled off the main header.
424 * This function returns EOF if the last queue has already been decoded, 0 if a
425 * queue was successfully decoded into '*queue', or an ofperr if there was a
426 * problem decoding 'reply'. */
428 ofputil_pull_queue_get_config_reply(struct ofpbuf
*msg
,
429 struct ofputil_queue_config
*queue
)
433 /* Pull OpenFlow header. */
434 raw
= ofpraw_pull_assert(msg
);
436 /* Pull protocol-specific ofp_queue_get_config_reply header (OF1.4
437 * doesn't have one at all). */
438 if (raw
== OFPRAW_OFPT10_QUEUE_GET_CONFIG_REPLY
) {
439 ofpbuf_pull(msg
, sizeof(struct ofp10_queue_get_config_reply
));
440 } else if (raw
== OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY
) {
441 ofpbuf_pull(msg
, sizeof(struct ofp11_queue_get_config_reply
));
443 ovs_assert(raw
== OFPRAW_OFPST14_QUEUE_DESC_REPLY
);
446 raw
= ofpraw_decode_assert(msg
->header
);
449 queue
->min_rate
= UINT16_MAX
;
450 queue
->max_rate
= UINT16_MAX
;
454 } else if (raw
== OFPRAW_OFPST14_QUEUE_DESC_REPLY
) {
455 return ofputil_pull_queue_get_config_reply14(msg
, queue
);
457 return ofputil_pull_queue_get_config_reply10(msg
, queue
);
462 print_queue_rate(struct ds
*string
, const char *name
, unsigned int rate
)
465 ds_put_format(string
, " %s:%u.%u%%", name
, rate
/ 10, rate
% 10);
466 } else if (rate
< UINT16_MAX
) {
467 ds_put_format(string
, " %s:(disabled)", name
);
471 /* qsort comparison function. */
473 compare_queues(const void *a_
, const void *b_
)
475 const struct ofputil_queue_config
*a
= a_
;
476 const struct ofputil_queue_config
*b
= b_
;
478 uint16_t ap
= ofp_to_u16(a
->port
);
479 uint16_t bp
= ofp_to_u16(b
->port
);
481 return ap
< bp
? -1 : 1;
484 uint32_t aq
= a
->queue
;
485 uint32_t bq
= b
->queue
;
486 return aq
< bq
? -1 : aq
> bq
;
490 ofputil_queue_get_config_reply_format(struct ds
*string
,
491 const struct ofp_header
*oh
,
492 const struct ofputil_port_map
*port_map
)
494 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
496 struct ofputil_queue_config
*queues
= NULL
;
497 size_t allocated_queues
= 0;
502 if (n
>= allocated_queues
) {
503 queues
= x2nrealloc(queues
, &allocated_queues
, sizeof *queues
);
505 retval
= ofputil_pull_queue_get_config_reply(&b
, &queues
[n
]);
512 qsort(queues
, n
, sizeof *queues
, compare_queues
);
514 ds_put_char(string
, ' ');
517 for (const struct ofputil_queue_config
*q
= queues
; q
< &queues
[n
]; q
++) {
518 if (q
->port
!= port
) {
521 ds_put_cstr(string
, "port=");
522 ofputil_format_port(port
, port_map
, string
);
523 ds_put_char(string
, '\n');
526 ds_put_format(string
, "queue %"PRIu32
":", q
->queue
);
527 print_queue_rate(string
, "min_rate", q
->min_rate
);
528 print_queue_rate(string
, "max_rate", q
->max_rate
);
529 ds_put_char(string
, '\n');
532 ds_chomp(string
, ' ');
535 return retval
!= EOF
? retval
: 0;
538 /* Parse a queue status request message into 'oqsr'.
539 * Returns 0 if successful, otherwise an OFPERR_* number. */
541 ofputil_decode_queue_stats_request(const struct ofp_header
*request
,
542 struct ofputil_queue_stats_request
*oqsr
)
544 switch ((enum ofp_version
)request
->version
) {
549 case OFP11_VERSION
: {
550 const struct ofp11_queue_stats_request
*qsr11
= ofpmsg_body(request
);
551 oqsr
->queue_id
= ntohl(qsr11
->queue_id
);
552 return ofputil_port_from_ofp11(qsr11
->port_no
, &oqsr
->port_no
);
555 case OFP10_VERSION
: {
556 const struct ofp10_queue_stats_request
*qsr10
= ofpmsg_body(request
);
557 oqsr
->queue_id
= ntohl(qsr10
->queue_id
);
558 oqsr
->port_no
= u16_to_ofp(ntohs(qsr10
->port_no
));
559 /* OF 1.0 uses OFPP_ALL for OFPP_ANY */
560 if (oqsr
->port_no
== OFPP_ALL
) {
561 oqsr
->port_no
= OFPP_ANY
;
571 /* Encode a queue stats request for 'oqsr', the encoded message
572 * will be for OpenFlow version 'ofp_version'. Returns message
573 * as a struct ofpbuf. Returns encoded message on success, NULL on error. */
575 ofputil_encode_queue_stats_request(
576 enum ofp_version ofp_version
,
577 const struct ofputil_queue_stats_request
*oqsr
)
579 struct ofpbuf
*request
;
581 switch (ofp_version
) {
586 case OFP15_VERSION
: {
587 struct ofp11_queue_stats_request
*req
;
588 request
= ofpraw_alloc(OFPRAW_OFPST11_QUEUE_REQUEST
, ofp_version
, 0);
589 req
= ofpbuf_put_zeros(request
, sizeof *req
);
590 req
->port_no
= ofputil_port_to_ofp11(oqsr
->port_no
);
591 req
->queue_id
= htonl(oqsr
->queue_id
);
594 case OFP10_VERSION
: {
595 struct ofp10_queue_stats_request
*req
;
596 request
= ofpraw_alloc(OFPRAW_OFPST10_QUEUE_REQUEST
, ofp_version
, 0);
597 req
= ofpbuf_put_zeros(request
, sizeof *req
);
598 /* OpenFlow 1.0 needs OFPP_ALL instead of OFPP_ANY */
599 req
->port_no
= htons(ofp_to_u16(oqsr
->port_no
== OFPP_ANY
600 ? OFPP_ALL
: oqsr
->port_no
));
601 req
->queue_id
= htonl(oqsr
->queue_id
);
612 ofputil_queue_stats_request_format(struct ds
*string
,
613 const struct ofp_header
*oh
,
614 const struct ofputil_port_map
*port_map
)
616 struct ofputil_queue_stats_request oqsr
;
619 error
= ofputil_decode_queue_stats_request(oh
, &oqsr
);
624 ds_put_cstr(string
, " port=");
625 ofputil_format_port(oqsr
.port_no
, port_map
, string
);
627 ds_put_cstr(string
, " queue=");
628 ofp_print_queue_name(string
, oqsr
.queue_id
);
633 /* Returns the number of queue stats elements in OFPTYPE_QUEUE_STATS_REPLY
636 ofputil_count_queue_stats(const struct ofp_header
*oh
)
638 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
639 ofpraw_pull_assert(&b
);
641 for (size_t n
= 0; ; n
++) {
642 struct ofputil_queue_stats qs
;
643 if (ofputil_decode_queue_stats(&qs
, &b
)) {
650 ofputil_queue_stats_from_ofp10(struct ofputil_queue_stats
*oqs
,
651 const struct ofp10_queue_stats
*qs10
)
653 oqs
->port_no
= u16_to_ofp(ntohs(qs10
->port_no
));
654 oqs
->queue_id
= ntohl(qs10
->queue_id
);
655 oqs
->tx_bytes
= ntohll(get_32aligned_be64(&qs10
->tx_bytes
));
656 oqs
->tx_packets
= ntohll(get_32aligned_be64(&qs10
->tx_packets
));
657 oqs
->tx_errors
= ntohll(get_32aligned_be64(&qs10
->tx_errors
));
658 oqs
->duration_sec
= oqs
->duration_nsec
= UINT32_MAX
;
664 ofputil_queue_stats_from_ofp11(struct ofputil_queue_stats
*oqs
,
665 const struct ofp11_queue_stats
*qs11
)
669 error
= ofputil_port_from_ofp11(qs11
->port_no
, &oqs
->port_no
);
674 oqs
->queue_id
= ntohl(qs11
->queue_id
);
675 oqs
->tx_bytes
= ntohll(qs11
->tx_bytes
);
676 oqs
->tx_packets
= ntohll(qs11
->tx_packets
);
677 oqs
->tx_errors
= ntohll(qs11
->tx_errors
);
678 oqs
->duration_sec
= oqs
->duration_nsec
= UINT32_MAX
;
684 ofputil_queue_stats_from_ofp13(struct ofputil_queue_stats
*oqs
,
685 const struct ofp13_queue_stats
*qs13
)
687 enum ofperr error
= ofputil_queue_stats_from_ofp11(oqs
, &qs13
->qs
);
689 oqs
->duration_sec
= ntohl(qs13
->duration_sec
);
690 oqs
->duration_nsec
= ntohl(qs13
->duration_nsec
);
697 ofputil_pull_ofp14_queue_stats(struct ofputil_queue_stats
*oqs
,
700 const struct ofp14_queue_stats
*qs14
;
703 qs14
= ofpbuf_try_pull(msg
, sizeof *qs14
);
705 return OFPERR_OFPBRC_BAD_LEN
;
708 len
= ntohs(qs14
->length
);
709 if (len
< sizeof *qs14
|| len
- sizeof *qs14
> msg
->size
) {
710 return OFPERR_OFPBRC_BAD_LEN
;
712 ofpbuf_pull(msg
, len
- sizeof *qs14
);
714 /* No properties yet defined, so ignore them for now. */
716 return ofputil_queue_stats_from_ofp13(oqs
, &qs14
->qs
);
719 /* Converts an OFPST_QUEUE_STATS reply in 'msg' into an abstract
720 * ofputil_queue_stats in 'qs'.
722 * Multiple OFPST_QUEUE_STATS replies can be packed into a single OpenFlow
723 * message. Calling this function multiple times for a single 'msg' iterates
724 * through the replies. The caller must initially leave 'msg''s layer pointers
725 * null and not modify them between calls.
727 * Returns 0 if successful, EOF if no replies were left in this 'msg',
728 * otherwise a positive errno value. */
730 ofputil_decode_queue_stats(struct ofputil_queue_stats
*qs
, struct ofpbuf
*msg
)
735 error
= (msg
->header
? ofpraw_decode(&raw
, msg
->header
)
736 : ofpraw_pull(&raw
, msg
));
743 } else if (raw
== OFPRAW_OFPST14_QUEUE_REPLY
) {
744 return ofputil_pull_ofp14_queue_stats(qs
, msg
);
745 } else if (raw
== OFPRAW_OFPST13_QUEUE_REPLY
) {
746 const struct ofp13_queue_stats
*qs13
;
748 qs13
= ofpbuf_try_pull(msg
, sizeof *qs13
);
752 return ofputil_queue_stats_from_ofp13(qs
, qs13
);
753 } else if (raw
== OFPRAW_OFPST11_QUEUE_REPLY
) {
754 const struct ofp11_queue_stats
*qs11
;
756 qs11
= ofpbuf_try_pull(msg
, sizeof *qs11
);
760 return ofputil_queue_stats_from_ofp11(qs
, qs11
);
761 } else if (raw
== OFPRAW_OFPST10_QUEUE_REPLY
) {
762 const struct ofp10_queue_stats
*qs10
;
764 qs10
= ofpbuf_try_pull(msg
, sizeof *qs10
);
768 return ofputil_queue_stats_from_ofp10(qs
, qs10
);
774 VLOG_WARN_RL(&rl
, "OFPST_QUEUE reply has %"PRIu32
" leftover "
775 "bytes at end", msg
->size
);
776 return OFPERR_OFPBRC_BAD_LEN
;
780 ofputil_queue_stats_to_ofp10(const struct ofputil_queue_stats
*oqs
,
781 struct ofp10_queue_stats
*qs10
)
783 qs10
->port_no
= htons(ofp_to_u16(oqs
->port_no
));
784 memset(qs10
->pad
, 0, sizeof qs10
->pad
);
785 qs10
->queue_id
= htonl(oqs
->queue_id
);
786 put_32aligned_be64(&qs10
->tx_bytes
, htonll(oqs
->tx_bytes
));
787 put_32aligned_be64(&qs10
->tx_packets
, htonll(oqs
->tx_packets
));
788 put_32aligned_be64(&qs10
->tx_errors
, htonll(oqs
->tx_errors
));
792 ofputil_queue_stats_to_ofp11(const struct ofputil_queue_stats
*oqs
,
793 struct ofp11_queue_stats
*qs11
)
795 qs11
->port_no
= ofputil_port_to_ofp11(oqs
->port_no
);
796 qs11
->queue_id
= htonl(oqs
->queue_id
);
797 qs11
->tx_bytes
= htonll(oqs
->tx_bytes
);
798 qs11
->tx_packets
= htonll(oqs
->tx_packets
);
799 qs11
->tx_errors
= htonll(oqs
->tx_errors
);
803 ofputil_queue_stats_to_ofp13(const struct ofputil_queue_stats
*oqs
,
804 struct ofp13_queue_stats
*qs13
)
806 ofputil_queue_stats_to_ofp11(oqs
, &qs13
->qs
);
807 if (oqs
->duration_sec
!= UINT32_MAX
) {
808 qs13
->duration_sec
= htonl(oqs
->duration_sec
);
809 qs13
->duration_nsec
= htonl(oqs
->duration_nsec
);
811 qs13
->duration_sec
= OVS_BE32_MAX
;
812 qs13
->duration_nsec
= OVS_BE32_MAX
;
817 ofputil_queue_stats_to_ofp14(const struct ofputil_queue_stats
*oqs
,
818 struct ofp14_queue_stats
*qs14
)
820 qs14
->length
= htons(sizeof *qs14
);
821 memset(qs14
->pad
, 0, sizeof qs14
->pad
);
822 ofputil_queue_stats_to_ofp13(oqs
, &qs14
->qs
);
826 /* Encode a queue stat for 'oqs' and append it to 'replies'. */
828 ofputil_append_queue_stat(struct ovs_list
*replies
,
829 const struct ofputil_queue_stats
*oqs
)
831 switch (ofpmp_version(replies
)) {
832 case OFP13_VERSION
: {
833 struct ofp13_queue_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
834 ofputil_queue_stats_to_ofp13(oqs
, reply
);
839 case OFP11_VERSION
: {
840 struct ofp11_queue_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
841 ofputil_queue_stats_to_ofp11(oqs
, reply
);
845 case OFP10_VERSION
: {
846 struct ofp10_queue_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
847 ofputil_queue_stats_to_ofp10(oqs
, reply
);
852 case OFP15_VERSION
: {
853 struct ofp14_queue_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
854 ofputil_queue_stats_to_ofp14(oqs
, reply
);
864 print_queue_stat(struct ds
*string
, const char *leader
, uint64_t stat
,
867 ds_put_cstr(string
, leader
);
868 if (stat
!= UINT64_MAX
) {
869 ds_put_format(string
, "%"PRIu64
, stat
);
871 ds_put_char(string
, '?');
874 ds_put_cstr(string
, ", ");
876 ds_put_cstr(string
, "\n");
881 ofputil_queue_stats_reply_format(struct ds
*string
,
882 const struct ofp_header
*oh
,
883 const struct ofputil_port_map
*port_map
,
886 ds_put_format(string
, " %"PRIuSIZE
" queues\n",
887 ofputil_count_queue_stats(oh
));
892 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
894 struct ofputil_queue_stats qs
;
897 retval
= ofputil_decode_queue_stats(&qs
, &b
);
899 return retval
!= EOF
? retval
: 0;
902 ds_put_cstr(string
, " port ");
903 ofputil_format_port(qs
.port_no
, port_map
, string
);
904 ds_put_cstr(string
, " queue ");
905 ofp_print_queue_name(string
, qs
.queue_id
);
906 ds_put_cstr(string
, ": ");
908 print_queue_stat(string
, "bytes=", qs
.tx_bytes
, 1);
909 print_queue_stat(string
, "pkts=", qs
.tx_packets
, 1);
910 print_queue_stat(string
, "errors=", qs
.tx_errors
, 1);
912 ds_put_cstr(string
, "duration=");
913 if (qs
.duration_sec
!= UINT32_MAX
) {
914 ofp_print_duration(string
, qs
.duration_sec
, qs
.duration_nsec
);
916 ds_put_char(string
, '?');
918 ds_put_char(string
, '\n');