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-port.h"
23 #include "openvswitch/ofp-prop.h"
24 #include "openvswitch/ofpbuf.h"
25 #include "openvswitch/vlog.h"
28 VLOG_DEFINE_THIS_MODULE(ofp_queue
);
30 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 5);
32 /* Constructs and returns an OFPT_QUEUE_GET_CONFIG request for the specified
33 * 'port' and 'queue', suitable for OpenFlow version 'version'.
35 * 'queue' is honored only for OpenFlow 1.4 and later; older versions always
36 * request all queues. */
38 ofputil_encode_queue_get_config_request(enum ofp_version version
,
42 struct ofpbuf
*request
;
44 if (version
== OFP10_VERSION
) {
45 struct ofp10_queue_get_config_request
*qgcr10
;
47 request
= ofpraw_alloc(OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST
,
49 qgcr10
= ofpbuf_put_zeros(request
, sizeof *qgcr10
);
50 qgcr10
->port
= htons(ofp_to_u16(port
));
51 } else if (version
< OFP14_VERSION
) {
52 struct ofp11_queue_get_config_request
*qgcr11
;
54 request
= ofpraw_alloc(OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST
,
56 qgcr11
= ofpbuf_put_zeros(request
, sizeof *qgcr11
);
57 qgcr11
->port
= ofputil_port_to_ofp11(port
);
59 struct ofp14_queue_desc_request
*qdr14
;
61 request
= ofpraw_alloc(OFPRAW_OFPST14_QUEUE_DESC_REQUEST
,
63 qdr14
= ofpbuf_put_zeros(request
, sizeof *qdr14
);
64 qdr14
->port
= ofputil_port_to_ofp11(port
);
65 qdr14
->queue
= htonl(queue
);
71 /* Parses OFPT_QUEUE_GET_CONFIG request 'oh', storing the port specified by the
72 * request into '*port'. Returns 0 if successful, otherwise an OpenFlow error
75 ofputil_decode_queue_get_config_request(const struct ofp_header
*oh
,
76 ofp_port_t
*port
, uint32_t *queue
)
78 const struct ofp10_queue_get_config_request
*qgcr10
;
79 const struct ofp11_queue_get_config_request
*qgcr11
;
80 const struct ofp14_queue_desc_request
*qdr14
;
81 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
82 enum ofpraw raw
= ofpraw_pull_assert(&b
);
85 case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST
:
87 *port
= u16_to_ofp(ntohs(qgcr10
->port
));
91 case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST
:
94 enum ofperr error
= ofputil_port_from_ofp11(qgcr11
->port
, port
);
95 if (error
|| *port
== OFPP_ANY
) {
100 case OFPRAW_OFPST14_QUEUE_DESC_REQUEST
:
102 *queue
= ntohl(qdr14
->queue
);
103 return ofputil_port_from_ofp11(qdr14
->port
, port
);
109 return (ofp_to_u16(*port
) < ofp_to_u16(OFPP_MAX
)
111 : OFPERR_OFPQOFC_BAD_PORT
);
114 /* Constructs and returns the beginning of a reply to
115 * OFPT_QUEUE_GET_CONFIG_REQUEST or OFPMP_QUEUE_DESC request 'oh'. The caller
116 * may append information about individual queues with
117 * ofputil_append_queue_get_config_reply(). */
119 ofputil_start_queue_get_config_reply(const struct ofp_header
*request
,
120 struct ovs_list
*replies
)
122 struct ofpbuf
*reply
;
126 ovs_assert(!ofputil_decode_queue_get_config_request(request
, &port
,
129 enum ofpraw raw
= ofpraw_decode_assert(request
);
131 case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST
:
132 reply
= ofpraw_alloc_reply(OFPRAW_OFPT10_QUEUE_GET_CONFIG_REPLY
,
134 struct ofp10_queue_get_config_reply
*qgcr10
135 = ofpbuf_put_zeros(reply
, sizeof *qgcr10
);
136 qgcr10
->port
= htons(ofp_to_u16(port
));
139 case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST
:
140 reply
= ofpraw_alloc_reply(OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY
,
142 struct ofp11_queue_get_config_reply
*qgcr11
143 = ofpbuf_put_zeros(reply
, sizeof *qgcr11
);
144 qgcr11
->port
= ofputil_port_to_ofp11(port
);
147 case OFPRAW_OFPST14_QUEUE_DESC_REQUEST
:
148 reply
= ofpraw_alloc_stats_reply(request
, 0);
155 ovs_list_init(replies
);
156 ovs_list_push_back(replies
, &reply
->list_node
);
160 put_ofp10_queue_rate(struct ofpbuf
*reply
,
161 enum ofp10_queue_properties property
, uint16_t rate
)
163 if (rate
!= UINT16_MAX
) {
164 struct ofp10_queue_prop_rate
*oqpr
;
166 oqpr
= ofpbuf_put_zeros(reply
, sizeof *oqpr
);
167 oqpr
->prop_header
.property
= htons(property
);
168 oqpr
->prop_header
.len
= htons(sizeof *oqpr
);
169 oqpr
->rate
= htons(rate
);
174 put_ofp14_queue_rate(struct ofpbuf
*reply
,
175 enum ofp14_queue_desc_prop_type type
, uint16_t rate
)
177 if (rate
!= UINT16_MAX
) {
178 ofpprop_put_u16(reply
, type
, rate
);
183 ofputil_append_queue_get_config_reply(const struct ofputil_queue_config
*qc
,
184 struct ovs_list
*replies
)
186 enum ofp_version ofp_version
= ofpmp_version(replies
);
187 struct ofpbuf
*reply
= ofpbuf_from_list(ovs_list_back(replies
));
188 size_t start_ofs
= reply
->size
;
192 if (ofp_version
< OFP14_VERSION
) {
193 if (ofp_version
< OFP12_VERSION
) {
194 struct ofp10_packet_queue
*opq10
;
196 opq10
= ofpbuf_put_zeros(reply
, sizeof *opq10
);
197 opq10
->queue_id
= htonl(qc
->queue
);
198 len_ofs
= (char *) &opq10
->len
- (char *) reply
->data
;
200 struct ofp12_packet_queue
*opq12
;
202 opq12
= ofpbuf_put_zeros(reply
, sizeof *opq12
);
203 opq12
->port
= ofputil_port_to_ofp11(qc
->port
);
204 opq12
->queue_id
= htonl(qc
->queue
);
205 len_ofs
= (char *) &opq12
->len
- (char *) reply
->data
;
208 put_ofp10_queue_rate(reply
, OFPQT10_MIN_RATE
, qc
->min_rate
);
209 put_ofp10_queue_rate(reply
, OFPQT11_MAX_RATE
, qc
->max_rate
);
211 struct ofp14_queue_desc
*oqd
= ofpbuf_put_zeros(reply
, sizeof *oqd
);
212 oqd
->port_no
= ofputil_port_to_ofp11(qc
->port
);
213 oqd
->queue_id
= htonl(qc
->queue
);
214 len_ofs
= (char *) &oqd
->len
- (char *) reply
->data
;
215 put_ofp14_queue_rate(reply
, OFPQDPT14_MIN_RATE
, qc
->min_rate
);
216 put_ofp14_queue_rate(reply
, OFPQDPT14_MAX_RATE
, qc
->max_rate
);
219 len
= ofpbuf_at(reply
, len_ofs
, sizeof *len
);
220 *len
= htons(reply
->size
- start_ofs
);
222 if (ofp_version
>= OFP14_VERSION
) {
223 ofpmp_postappend(replies
, start_ofs
);
228 parse_ofp10_queue_rate(const struct ofp10_queue_prop_header
*hdr
,
231 const struct ofp10_queue_prop_rate
*oqpr
;
233 if (hdr
->len
== htons(sizeof *oqpr
)) {
234 oqpr
= (const struct ofp10_queue_prop_rate
*) hdr
;
235 *rate
= ntohs(oqpr
->rate
);
238 return OFPERR_OFPBRC_BAD_LEN
;
243 ofputil_pull_queue_get_config_reply10(struct ofpbuf
*msg
,
244 struct ofputil_queue_config
*queue
)
246 const struct ofp_header
*oh
= msg
->header
;
247 unsigned int opq_len
; /* Length of protocol-specific queue header. */
248 unsigned int len
; /* Total length of queue + properties. */
250 /* Obtain the port number from the message header. */
251 if (oh
->version
== OFP10_VERSION
) {
252 const struct ofp10_queue_get_config_reply
*oqgcr10
= msg
->msg
;
253 queue
->port
= u16_to_ofp(ntohs(oqgcr10
->port
));
255 const struct ofp11_queue_get_config_reply
*oqgcr11
= msg
->msg
;
256 enum ofperr error
= ofputil_port_from_ofp11(oqgcr11
->port
,
263 /* Pull off the queue header and get the queue number and length. */
264 if (oh
->version
< OFP12_VERSION
) {
265 const struct ofp10_packet_queue
*opq10
;
266 opq10
= ofpbuf_try_pull(msg
, sizeof *opq10
);
268 return OFPERR_OFPBRC_BAD_LEN
;
270 queue
->queue
= ntohl(opq10
->queue_id
);
271 len
= ntohs(opq10
->len
);
272 opq_len
= sizeof *opq10
;
274 const struct ofp12_packet_queue
*opq12
;
275 opq12
= ofpbuf_try_pull(msg
, sizeof *opq12
);
277 return OFPERR_OFPBRC_BAD_LEN
;
279 queue
->queue
= ntohl(opq12
->queue_id
);
280 len
= ntohs(opq12
->len
);
281 opq_len
= sizeof *opq12
;
285 if (len
< opq_len
|| len
> msg
->size
+ opq_len
|| len
% 8) {
286 return OFPERR_OFPBRC_BAD_LEN
;
290 /* Pull properties. The format of these properties differs from used in
291 * OF1.4+ so we can't use the common property functions. */
293 const struct ofp10_queue_prop_header
*hdr
;
294 unsigned int property
;
295 unsigned int prop_len
;
296 enum ofperr error
= 0;
298 hdr
= ofpbuf_at_assert(msg
, 0, sizeof *hdr
);
299 prop_len
= ntohs(hdr
->len
);
300 if (prop_len
< sizeof *hdr
|| prop_len
> len
|| prop_len
% 8) {
301 return OFPERR_OFPBRC_BAD_LEN
;
304 property
= ntohs(hdr
->property
);
306 case OFPQT10_MIN_RATE
:
307 error
= parse_ofp10_queue_rate(hdr
, &queue
->min_rate
);
310 case OFPQT11_MAX_RATE
:
311 error
= parse_ofp10_queue_rate(hdr
, &queue
->max_rate
);
315 VLOG_INFO_RL(&rl
, "unknown queue property %u", property
);
322 ofpbuf_pull(msg
, prop_len
);
329 ofputil_pull_queue_get_config_reply14(struct ofpbuf
*msg
,
330 struct ofputil_queue_config
*queue
)
332 struct ofp14_queue_desc
*oqd14
= ofpbuf_try_pull(msg
, sizeof *oqd14
);
334 return OFPERR_OFPBRC_BAD_LEN
;
336 enum ofperr error
= ofputil_port_from_ofp11(oqd14
->port_no
, &queue
->port
);
340 queue
->queue
= ntohl(oqd14
->queue_id
);
343 unsigned int len
= ntohs(oqd14
->len
);
344 if (len
< sizeof *oqd14
|| len
> msg
->size
+ sizeof *oqd14
|| len
% 8) {
345 return OFPERR_OFPBRC_BAD_LEN
;
347 len
-= sizeof *oqd14
;
349 struct ofpbuf properties
= ofpbuf_const_initializer(ofpbuf_pull(msg
, len
),
351 while (properties
.size
> 0) {
352 struct ofpbuf payload
;
355 error
= ofpprop_pull(&properties
, &payload
, &type
);
361 case OFPQDPT14_MIN_RATE
:
362 error
= ofpprop_parse_u16(&payload
, &queue
->min_rate
);
365 case OFPQDPT14_MAX_RATE
:
366 error
= ofpprop_parse_u16(&payload
, &queue
->max_rate
);
370 error
= OFPPROP_UNKNOWN(true, "queue desc", type
);
382 /* Decodes information about a queue from the OFPT_QUEUE_GET_CONFIG_REPLY in
383 * 'reply' and stores it in '*queue'. ofputil_decode_queue_get_config_reply()
384 * must already have pulled off the main header.
386 * This function returns EOF if the last queue has already been decoded, 0 if a
387 * queue was successfully decoded into '*queue', or an ofperr if there was a
388 * problem decoding 'reply'. */
390 ofputil_pull_queue_get_config_reply(struct ofpbuf
*msg
,
391 struct ofputil_queue_config
*queue
)
395 /* Pull OpenFlow header. */
396 raw
= ofpraw_pull_assert(msg
);
398 /* Pull protocol-specific ofp_queue_get_config_reply header (OF1.4
399 * doesn't have one at all). */
400 if (raw
== OFPRAW_OFPT10_QUEUE_GET_CONFIG_REPLY
) {
401 ofpbuf_pull(msg
, sizeof(struct ofp10_queue_get_config_reply
));
402 } else if (raw
== OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY
) {
403 ofpbuf_pull(msg
, sizeof(struct ofp11_queue_get_config_reply
));
405 ovs_assert(raw
== OFPRAW_OFPST14_QUEUE_DESC_REPLY
);
408 raw
= ofpraw_decode_assert(msg
->header
);
411 queue
->min_rate
= UINT16_MAX
;
412 queue
->max_rate
= UINT16_MAX
;
416 } else if (raw
== OFPRAW_OFPST14_QUEUE_DESC_REPLY
) {
417 return ofputil_pull_queue_get_config_reply14(msg
, queue
);
419 return ofputil_pull_queue_get_config_reply10(msg
, queue
);
423 /* Parse a queue status request message into 'oqsr'.
424 * Returns 0 if successful, otherwise an OFPERR_* number. */
426 ofputil_decode_queue_stats_request(const struct ofp_header
*request
,
427 struct ofputil_queue_stats_request
*oqsr
)
429 switch ((enum ofp_version
)request
->version
) {
435 case OFP11_VERSION
: {
436 const struct ofp11_queue_stats_request
*qsr11
= ofpmsg_body(request
);
437 oqsr
->queue_id
= ntohl(qsr11
->queue_id
);
438 return ofputil_port_from_ofp11(qsr11
->port_no
, &oqsr
->port_no
);
441 case OFP10_VERSION
: {
442 const struct ofp10_queue_stats_request
*qsr10
= ofpmsg_body(request
);
443 oqsr
->queue_id
= ntohl(qsr10
->queue_id
);
444 oqsr
->port_no
= u16_to_ofp(ntohs(qsr10
->port_no
));
445 /* OF 1.0 uses OFPP_ALL for OFPP_ANY */
446 if (oqsr
->port_no
== OFPP_ALL
) {
447 oqsr
->port_no
= OFPP_ANY
;
457 /* Encode a queue stats request for 'oqsr', the encoded message
458 * will be for OpenFlow version 'ofp_version'. Returns message
459 * as a struct ofpbuf. Returns encoded message on success, NULL on error. */
461 ofputil_encode_queue_stats_request(
462 enum ofp_version ofp_version
,
463 const struct ofputil_queue_stats_request
*oqsr
)
465 struct ofpbuf
*request
;
467 switch (ofp_version
) {
473 case OFP16_VERSION
: {
474 struct ofp11_queue_stats_request
*req
;
475 request
= ofpraw_alloc(OFPRAW_OFPST11_QUEUE_REQUEST
, ofp_version
, 0);
476 req
= ofpbuf_put_zeros(request
, sizeof *req
);
477 req
->port_no
= ofputil_port_to_ofp11(oqsr
->port_no
);
478 req
->queue_id
= htonl(oqsr
->queue_id
);
481 case OFP10_VERSION
: {
482 struct ofp10_queue_stats_request
*req
;
483 request
= ofpraw_alloc(OFPRAW_OFPST10_QUEUE_REQUEST
, ofp_version
, 0);
484 req
= ofpbuf_put_zeros(request
, sizeof *req
);
485 /* OpenFlow 1.0 needs OFPP_ALL instead of OFPP_ANY */
486 req
->port_no
= htons(ofp_to_u16(oqsr
->port_no
== OFPP_ANY
487 ? OFPP_ALL
: oqsr
->port_no
));
488 req
->queue_id
= htonl(oqsr
->queue_id
);
498 /* Returns the number of queue stats elements in OFPTYPE_QUEUE_STATS_REPLY
501 ofputil_count_queue_stats(const struct ofp_header
*oh
)
503 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
504 ofpraw_pull_assert(&b
);
506 for (size_t n
= 0; ; n
++) {
507 struct ofputil_queue_stats qs
;
508 if (ofputil_decode_queue_stats(&qs
, &b
)) {
515 ofputil_queue_stats_from_ofp10(struct ofputil_queue_stats
*oqs
,
516 const struct ofp10_queue_stats
*qs10
)
518 oqs
->port_no
= u16_to_ofp(ntohs(qs10
->port_no
));
519 oqs
->queue_id
= ntohl(qs10
->queue_id
);
520 oqs
->tx_bytes
= ntohll(get_32aligned_be64(&qs10
->tx_bytes
));
521 oqs
->tx_packets
= ntohll(get_32aligned_be64(&qs10
->tx_packets
));
522 oqs
->tx_errors
= ntohll(get_32aligned_be64(&qs10
->tx_errors
));
523 oqs
->duration_sec
= oqs
->duration_nsec
= UINT32_MAX
;
529 ofputil_queue_stats_from_ofp11(struct ofputil_queue_stats
*oqs
,
530 const struct ofp11_queue_stats
*qs11
)
534 error
= ofputil_port_from_ofp11(qs11
->port_no
, &oqs
->port_no
);
539 oqs
->queue_id
= ntohl(qs11
->queue_id
);
540 oqs
->tx_bytes
= ntohll(qs11
->tx_bytes
);
541 oqs
->tx_packets
= ntohll(qs11
->tx_packets
);
542 oqs
->tx_errors
= ntohll(qs11
->tx_errors
);
543 oqs
->duration_sec
= oqs
->duration_nsec
= UINT32_MAX
;
549 ofputil_queue_stats_from_ofp13(struct ofputil_queue_stats
*oqs
,
550 const struct ofp13_queue_stats
*qs13
)
552 enum ofperr error
= ofputil_queue_stats_from_ofp11(oqs
, &qs13
->qs
);
554 oqs
->duration_sec
= ntohl(qs13
->duration_sec
);
555 oqs
->duration_nsec
= ntohl(qs13
->duration_nsec
);
562 ofputil_pull_ofp14_queue_stats(struct ofputil_queue_stats
*oqs
,
565 const struct ofp14_queue_stats
*qs14
;
568 qs14
= ofpbuf_try_pull(msg
, sizeof *qs14
);
570 return OFPERR_OFPBRC_BAD_LEN
;
573 len
= ntohs(qs14
->length
);
574 if (len
< sizeof *qs14
|| len
- sizeof *qs14
> msg
->size
) {
575 return OFPERR_OFPBRC_BAD_LEN
;
577 ofpbuf_pull(msg
, len
- sizeof *qs14
);
579 /* No properties yet defined, so ignore them for now. */
581 return ofputil_queue_stats_from_ofp13(oqs
, &qs14
->qs
);
584 /* Converts an OFPST_QUEUE_STATS reply in 'msg' into an abstract
585 * ofputil_queue_stats in 'qs'.
587 * Multiple OFPST_QUEUE_STATS replies can be packed into a single OpenFlow
588 * message. Calling this function multiple times for a single 'msg' iterates
589 * through the replies. The caller must initially leave 'msg''s layer pointers
590 * null and not modify them between calls.
592 * Returns 0 if successful, EOF if no replies were left in this 'msg',
593 * otherwise a positive errno value. */
595 ofputil_decode_queue_stats(struct ofputil_queue_stats
*qs
, struct ofpbuf
*msg
)
600 error
= (msg
->header
? ofpraw_decode(&raw
, msg
->header
)
601 : ofpraw_pull(&raw
, msg
));
608 } else if (raw
== OFPRAW_OFPST14_QUEUE_REPLY
) {
609 return ofputil_pull_ofp14_queue_stats(qs
, msg
);
610 } else if (raw
== OFPRAW_OFPST13_QUEUE_REPLY
) {
611 const struct ofp13_queue_stats
*qs13
;
613 qs13
= ofpbuf_try_pull(msg
, sizeof *qs13
);
617 return ofputil_queue_stats_from_ofp13(qs
, qs13
);
618 } else if (raw
== OFPRAW_OFPST11_QUEUE_REPLY
) {
619 const struct ofp11_queue_stats
*qs11
;
621 qs11
= ofpbuf_try_pull(msg
, sizeof *qs11
);
625 return ofputil_queue_stats_from_ofp11(qs
, qs11
);
626 } else if (raw
== OFPRAW_OFPST10_QUEUE_REPLY
) {
627 const struct ofp10_queue_stats
*qs10
;
629 qs10
= ofpbuf_try_pull(msg
, sizeof *qs10
);
633 return ofputil_queue_stats_from_ofp10(qs
, qs10
);
639 VLOG_WARN_RL(&rl
, "OFPST_QUEUE reply has %"PRIu32
" leftover "
640 "bytes at end", msg
->size
);
641 return OFPERR_OFPBRC_BAD_LEN
;
645 ofputil_queue_stats_to_ofp10(const struct ofputil_queue_stats
*oqs
,
646 struct ofp10_queue_stats
*qs10
)
648 qs10
->port_no
= htons(ofp_to_u16(oqs
->port_no
));
649 memset(qs10
->pad
, 0, sizeof qs10
->pad
);
650 qs10
->queue_id
= htonl(oqs
->queue_id
);
651 put_32aligned_be64(&qs10
->tx_bytes
, htonll(oqs
->tx_bytes
));
652 put_32aligned_be64(&qs10
->tx_packets
, htonll(oqs
->tx_packets
));
653 put_32aligned_be64(&qs10
->tx_errors
, htonll(oqs
->tx_errors
));
657 ofputil_queue_stats_to_ofp11(const struct ofputil_queue_stats
*oqs
,
658 struct ofp11_queue_stats
*qs11
)
660 qs11
->port_no
= ofputil_port_to_ofp11(oqs
->port_no
);
661 qs11
->queue_id
= htonl(oqs
->queue_id
);
662 qs11
->tx_bytes
= htonll(oqs
->tx_bytes
);
663 qs11
->tx_packets
= htonll(oqs
->tx_packets
);
664 qs11
->tx_errors
= htonll(oqs
->tx_errors
);
668 ofputil_queue_stats_to_ofp13(const struct ofputil_queue_stats
*oqs
,
669 struct ofp13_queue_stats
*qs13
)
671 ofputil_queue_stats_to_ofp11(oqs
, &qs13
->qs
);
672 if (oqs
->duration_sec
!= UINT32_MAX
) {
673 qs13
->duration_sec
= htonl(oqs
->duration_sec
);
674 qs13
->duration_nsec
= htonl(oqs
->duration_nsec
);
676 qs13
->duration_sec
= OVS_BE32_MAX
;
677 qs13
->duration_nsec
= OVS_BE32_MAX
;
682 ofputil_queue_stats_to_ofp14(const struct ofputil_queue_stats
*oqs
,
683 struct ofp14_queue_stats
*qs14
)
685 qs14
->length
= htons(sizeof *qs14
);
686 memset(qs14
->pad
, 0, sizeof qs14
->pad
);
687 ofputil_queue_stats_to_ofp13(oqs
, &qs14
->qs
);
691 /* Encode a queue stat for 'oqs' and append it to 'replies'. */
693 ofputil_append_queue_stat(struct ovs_list
*replies
,
694 const struct ofputil_queue_stats
*oqs
)
696 switch (ofpmp_version(replies
)) {
697 case OFP13_VERSION
: {
698 struct ofp13_queue_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
699 ofputil_queue_stats_to_ofp13(oqs
, reply
);
704 case OFP11_VERSION
: {
705 struct ofp11_queue_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
706 ofputil_queue_stats_to_ofp11(oqs
, reply
);
710 case OFP10_VERSION
: {
711 struct ofp10_queue_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
712 ofputil_queue_stats_to_ofp10(oqs
, reply
);
718 case OFP16_VERSION
: {
719 struct ofp14_queue_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
720 ofputil_queue_stats_to_ofp14(oqs
, reply
);