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-port.h"
20 #include "byte-order.h"
22 #include "openflow/intel-ext.h"
23 #include "openvswitch/json.h"
24 #include "openvswitch/ofp-errors.h"
25 #include "openvswitch/ofp-msgs.h"
26 #include "openvswitch/ofp-print.h"
27 #include "openvswitch/ofp-prop.h"
28 #include "openvswitch/ofpbuf.h"
29 #include "openvswitch/vlog.h"
31 VLOG_DEFINE_THIS_MODULE(ofp_port
);
33 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 5);
35 /* ofputil_port_map. */
38 ofputil_port_map_init(struct ofputil_port_map
*map
)
40 namemap_init(&map
->map
);
44 ofputil_port_map_put(struct ofputil_port_map
*map
,
45 ofp_port_t ofp_port
, const char *name
)
47 namemap_put(&map
->map
, ofp_to_u16(ofp_port
), name
);
51 ofputil_port_map_get_name(const struct ofputil_port_map
*map
,
54 struct namemap_node
*node
56 ? namemap_find_by_number(&map
->map
, ofp_to_u16(ofp_port
))
58 return node
&& !node
->duplicate
? node
->name
: NULL
;
62 ofputil_port_map_get_number(const struct ofputil_port_map
*map
,
65 struct namemap_node
*node
66 = map
? namemap_find_by_name(&map
->map
, name
) : NULL
;
67 return node
&& !node
->duplicate
? u16_to_ofp(node
->number
) : OFPP_NONE
;
71 ofputil_port_map_destroy(struct ofputil_port_map
*map
)
73 namemap_destroy(&map
->map
);
76 /* Converts the OpenFlow 1.1+ port number 'ofp11_port' into an OpenFlow 1.0
77 * port number and stores the latter in '*ofp10_port', for the purpose of
78 * decoding OpenFlow 1.1+ protocol messages. Returns 0 if successful,
79 * otherwise an OFPERR_* number. On error, stores OFPP_NONE in '*ofp10_port'.
81 * See the definition of OFP11_MAX for an explanation of the mapping. */
83 ofputil_port_from_ofp11(ovs_be32 ofp11_port
, ofp_port_t
*ofp10_port
)
85 uint32_t ofp11_port_h
= ntohl(ofp11_port
);
87 if (ofp11_port_h
< ofp_to_u16(OFPP_MAX
)) {
88 *ofp10_port
= u16_to_ofp(ofp11_port_h
);
90 } else if (ofp11_port_h
>= ofp11_to_u32(OFPP11_MAX
)) {
91 *ofp10_port
= u16_to_ofp(ofp11_port_h
- OFPP11_OFFSET
);
94 *ofp10_port
= OFPP_NONE
;
96 static struct vlog_rate_limit rll
= VLOG_RATE_LIMIT_INIT(1, 5);
97 VLOG_WARN_RL(&rll
, "port %"PRIu32
" is outside the supported "
98 "range 0 through %d or 0x%"PRIx32
" through 0x%"PRIx32
,
99 ofp11_port_h
, ofp_to_u16(OFPP_MAX
) - 1,
100 ofp11_to_u32(OFPP11_MAX
), UINT32_MAX
);
102 return OFPERR_OFPBAC_BAD_OUT_PORT
;
106 /* Returns the OpenFlow 1.1+ port number equivalent to the OpenFlow 1.0 port
107 * number 'ofp10_port', for encoding OpenFlow 1.1+ protocol messages.
109 * See the definition of OFP11_MAX for an explanation of the mapping. */
111 ofputil_port_to_ofp11(ofp_port_t ofp10_port
)
113 return htonl(ofp_to_u16(ofp10_port
) < ofp_to_u16(OFPP_MAX
)
114 ? ofp_to_u16(ofp10_port
)
115 : ofp_to_u16(ofp10_port
) + OFPP11_OFFSET
);
118 #define OFPUTIL_NAMED_PORTS \
119 OFPUTIL_NAMED_PORT(IN_PORT) \
120 OFPUTIL_NAMED_PORT(TABLE) \
121 OFPUTIL_NAMED_PORT(NORMAL) \
122 OFPUTIL_NAMED_PORT(FLOOD) \
123 OFPUTIL_NAMED_PORT(ALL) \
124 OFPUTIL_NAMED_PORT(CONTROLLER) \
125 OFPUTIL_NAMED_PORT(LOCAL) \
126 OFPUTIL_NAMED_PORT(ANY) \
127 OFPUTIL_NAMED_PORT(UNSET)
129 /* For backwards compatibility, so that "none" is recognized as OFPP_ANY */
130 #define OFPUTIL_NAMED_PORTS_WITH_NONE \
131 OFPUTIL_NAMED_PORTS \
132 OFPUTIL_NAMED_PORT(NONE)
134 /* Stores the port number represented by 's' into '*portp'. 's' may be an
135 * integer or, for reserved ports, the standard OpenFlow name for the port
136 * (e.g. "LOCAL"). If 'port_map' is nonnull, also accepts names in it (quoted
139 * Returns true if successful, false if 's' is not a valid OpenFlow port number
140 * or name. The caller should issue an error message in this case, because
141 * this function usually does not. (This gives the caller an opportunity to
142 * look up the port name another way, e.g. by contacting the switch and listing
143 * the names of all its ports).
145 * This function accepts OpenFlow 1.0 port numbers. It also accepts a subset
146 * of OpenFlow 1.1+ port numbers, mapping those port numbers into the 16-bit
147 * range as described in include/openflow/openflow-1.1.h. */
149 ofputil_port_from_string(const char *s
,
150 const struct ofputil_port_map
*port_map
,
153 unsigned int port32
; /* int is at least 32 bits wide. */
156 VLOG_WARN("Negative value %s is not a valid port number.", s
);
160 if (str_to_uint(s
, 10, &port32
)) {
161 if (port32
< ofp_to_u16(OFPP_MAX
)) {
163 } else if (port32
< ofp_to_u16(OFPP_FIRST_RESV
)) {
164 VLOG_WARN("port %u is a reserved OF1.0 port number that will "
165 "be translated to %u when talking to an OF1.1 or "
166 "later controller", port32
, port32
+ OFPP11_OFFSET
);
167 } else if (port32
<= ofp_to_u16(OFPP_LAST_RESV
)) {
168 char name
[OFP_MAX_PORT_NAME_LEN
];
170 ofputil_port_to_string(u16_to_ofp(port32
), NULL
,
172 VLOG_WARN_ONCE("referring to port %s as %"PRIu32
" is deprecated "
173 "for compatibility with OpenFlow 1.1 and later",
175 } else if (port32
< ofp11_to_u32(OFPP11_MAX
)) {
176 VLOG_WARN("port %u is outside the supported range 0 through "
177 "%x or 0x%x through 0x%"PRIx32
, port32
,
178 UINT16_MAX
, ofp11_to_u32(OFPP11_MAX
), UINT32_MAX
);
181 port32
-= OFPP11_OFFSET
;
184 *portp
= u16_to_ofp(port32
);
191 static const struct pair pairs
[] = {
192 #define OFPUTIL_NAMED_PORT(NAME) {#NAME, OFPP_##NAME},
193 OFPUTIL_NAMED_PORTS_WITH_NONE
194 #undef OFPUTIL_NAMED_PORT
196 const struct pair
*p
;
198 for (p
= pairs
; p
< &pairs
[ARRAY_SIZE(pairs
)]; p
++) {
199 if (!strcasecmp(s
, p
->name
)) {
205 ofp_port_t ofp_port
= OFPP_NONE
;
207 ofp_port
= ofputil_port_map_get_number(port_map
, s
);
209 size_t length
= strlen(s
);
212 && s
[length
- 1] == '"'
213 && json_string_unescape(s
+ 1, length
- 2, &name
)) {
214 ofp_port
= ofputil_port_map_get_number(port_map
, name
);
218 if (ofp_port
!= OFPP_NONE
) {
228 ofputil_port_get_reserved_name(ofp_port_t port
)
231 #define OFPUTIL_NAMED_PORT(NAME) case OFPP_##NAME: return #NAME;
233 #undef OFPUTIL_NAMED_PORT
240 /* Appends to 's' a string representation of the OpenFlow port number 'port'.
241 * Most ports' string representation is just the port number, but for special
242 * ports, e.g. OFPP_LOCAL, it is the name, e.g. "LOCAL". */
244 ofputil_format_port(ofp_port_t port
, const struct ofputil_port_map
*port_map
,
247 const char *reserved_name
= ofputil_port_get_reserved_name(port
);
249 ds_put_cstr(s
, reserved_name
);
253 const char *port_name
= ofputil_port_map_get_name(port_map
, port
);
255 namemap_put_name(port_name
, s
);
259 ds_put_format(s
, "%"PRIu32
, port
);
262 /* Puts in the 'bufsize' byte in 'namebuf' a null-terminated string
263 * representation of OpenFlow port number 'port'. Most ports are represented
264 * as just the port number, but special ports, e.g. OFPP_LOCAL, are represented
265 * by name, e.g. "LOCAL". */
267 ofputil_port_to_string(ofp_port_t port
,
268 const struct ofputil_port_map
*port_map
,
269 char *namebuf
, size_t bufsize
)
271 const char *reserved_name
= ofputil_port_get_reserved_name(port
);
273 ovs_strlcpy(namebuf
, reserved_name
, bufsize
);
277 const char *port_name
= ofputil_port_map_get_name(port_map
, port
);
279 struct ds s
= DS_EMPTY_INITIALIZER
;
280 namemap_put_name(port_name
, &s
);
281 ovs_strlcpy(namebuf
, ds_cstr(&s
), bufsize
);
286 snprintf(namebuf
, bufsize
, "%"PRIu32
, port
);
289 /* ofputil_port_config */
292 ofputil_port_config_to_name(uint32_t bit
)
294 enum ofputil_port_config pc
= bit
;
297 case OFPUTIL_PC_PORT_DOWN
: return "PORT_DOWN";
298 case OFPUTIL_PC_NO_STP
: return "NO_STP";
299 case OFPUTIL_PC_NO_RECV
: return "NO_RECV";
300 case OFPUTIL_PC_NO_RECV_STP
: return "NO_RECV_STP";
301 case OFPUTIL_PC_NO_FLOOD
: return "NO_FLOOD";
302 case OFPUTIL_PC_NO_FWD
: return "NO_FWD";
303 case OFPUTIL_PC_NO_PACKET_IN
: return "NO_PACKET_IN";
310 ofputil_port_config_format(struct ds
*s
, enum ofputil_port_config config
)
312 ofp_print_bit_names(s
, config
, ofputil_port_config_to_name
, ' ');
313 ds_put_char(s
, '\n');
316 /* ofputil_port_state */
319 ofputil_port_state_to_name(uint32_t bit
)
321 enum ofputil_port_state ps
= bit
;
324 case OFPUTIL_PS_LINK_DOWN
: return "LINK_DOWN";
325 case OFPUTIL_PS_BLOCKED
: return "BLOCKED";
326 case OFPUTIL_PS_LIVE
: return "LIVE";
328 case OFPUTIL_PS_STP_LISTEN
:
329 case OFPUTIL_PS_STP_LEARN
:
330 case OFPUTIL_PS_STP_FORWARD
:
331 case OFPUTIL_PS_STP_BLOCK
:
332 /* Handled elsewhere. */
340 ofputil_port_state_format(struct ds
*s
, enum ofputil_port_state state
)
342 enum ofputil_port_state stp_state
;
344 /* The STP state is a 2-bit field so it doesn't fit in with the bitmask
345 * pattern. We have to special case it.
347 * OVS doesn't support STP, so this field will always be 0 if we are
348 * talking to OVS, so we'd always print STP_LISTEN in that case.
349 * Therefore, we don't print anything at all if the value is STP_LISTEN, to
350 * avoid confusing users. */
351 stp_state
= state
& OFPUTIL_PS_STP_MASK
;
353 ds_put_cstr(s
, (stp_state
== OFPUTIL_PS_STP_LEARN
? "STP_LEARN"
354 : stp_state
== OFPUTIL_PS_STP_FORWARD
? "STP_FORWARD"
356 state
&= ~OFPUTIL_PS_STP_MASK
;
358 ofp_print_bit_names(s
, state
, ofputil_port_state_to_name
, ' ');
361 ofp_print_bit_names(s
, state
, ofputil_port_state_to_name
, ' ');
363 ds_put_char(s
, '\n');
366 /* ofputil_phy_port */
368 /* NETDEV_F_* to and from OFPPF_* and OFPPF10_*. */
369 BUILD_ASSERT_DECL((int) NETDEV_F_10MB_HD
== OFPPF_10MB_HD
); /* bit 0 */
370 BUILD_ASSERT_DECL((int) NETDEV_F_10MB_FD
== OFPPF_10MB_FD
); /* bit 1 */
371 BUILD_ASSERT_DECL((int) NETDEV_F_100MB_HD
== OFPPF_100MB_HD
); /* bit 2 */
372 BUILD_ASSERT_DECL((int) NETDEV_F_100MB_FD
== OFPPF_100MB_FD
); /* bit 3 */
373 BUILD_ASSERT_DECL((int) NETDEV_F_1GB_HD
== OFPPF_1GB_HD
); /* bit 4 */
374 BUILD_ASSERT_DECL((int) NETDEV_F_1GB_FD
== OFPPF_1GB_FD
); /* bit 5 */
375 BUILD_ASSERT_DECL((int) NETDEV_F_10GB_FD
== OFPPF_10GB_FD
); /* bit 6 */
377 /* NETDEV_F_ bits 11...15 are OFPPF10_ bits 7...11: */
378 BUILD_ASSERT_DECL((int) NETDEV_F_COPPER
== (OFPPF10_COPPER
<< 4));
379 BUILD_ASSERT_DECL((int) NETDEV_F_FIBER
== (OFPPF10_FIBER
<< 4));
380 BUILD_ASSERT_DECL((int) NETDEV_F_AUTONEG
== (OFPPF10_AUTONEG
<< 4));
381 BUILD_ASSERT_DECL((int) NETDEV_F_PAUSE
== (OFPPF10_PAUSE
<< 4));
382 BUILD_ASSERT_DECL((int) NETDEV_F_PAUSE_ASYM
== (OFPPF10_PAUSE_ASYM
<< 4));
384 static enum netdev_features
385 netdev_port_features_from_ofp10(ovs_be32 ofp10_
)
387 uint32_t ofp10
= ntohl(ofp10_
);
388 return (ofp10
& 0x7f) | ((ofp10
& 0xf80) << 4);
392 netdev_port_features_to_ofp10(enum netdev_features features
)
394 return htonl((features
& 0x7f) | ((features
& 0xf800) >> 4));
397 BUILD_ASSERT_DECL((int) NETDEV_F_10MB_HD
== OFPPF_10MB_HD
); /* bit 0 */
398 BUILD_ASSERT_DECL((int) NETDEV_F_10MB_FD
== OFPPF_10MB_FD
); /* bit 1 */
399 BUILD_ASSERT_DECL((int) NETDEV_F_100MB_HD
== OFPPF_100MB_HD
); /* bit 2 */
400 BUILD_ASSERT_DECL((int) NETDEV_F_100MB_FD
== OFPPF_100MB_FD
); /* bit 3 */
401 BUILD_ASSERT_DECL((int) NETDEV_F_1GB_HD
== OFPPF_1GB_HD
); /* bit 4 */
402 BUILD_ASSERT_DECL((int) NETDEV_F_1GB_FD
== OFPPF_1GB_FD
); /* bit 5 */
403 BUILD_ASSERT_DECL((int) NETDEV_F_10GB_FD
== OFPPF_10GB_FD
); /* bit 6 */
404 BUILD_ASSERT_DECL((int) NETDEV_F_40GB_FD
== OFPPF11_40GB_FD
); /* bit 7 */
405 BUILD_ASSERT_DECL((int) NETDEV_F_100GB_FD
== OFPPF11_100GB_FD
); /* bit 8 */
406 BUILD_ASSERT_DECL((int) NETDEV_F_1TB_FD
== OFPPF11_1TB_FD
); /* bit 9 */
407 BUILD_ASSERT_DECL((int) NETDEV_F_OTHER
== OFPPF11_OTHER
); /* bit 10 */
408 BUILD_ASSERT_DECL((int) NETDEV_F_COPPER
== OFPPF11_COPPER
); /* bit 11 */
409 BUILD_ASSERT_DECL((int) NETDEV_F_FIBER
== OFPPF11_FIBER
); /* bit 12 */
410 BUILD_ASSERT_DECL((int) NETDEV_F_AUTONEG
== OFPPF11_AUTONEG
); /* bit 13 */
411 BUILD_ASSERT_DECL((int) NETDEV_F_PAUSE
== OFPPF11_PAUSE
); /* bit 14 */
412 BUILD_ASSERT_DECL((int) NETDEV_F_PAUSE_ASYM
== OFPPF11_PAUSE_ASYM
);/* bit 15 */
414 static enum netdev_features
415 netdev_port_features_from_ofp11(ovs_be32 ofp11
)
417 return ntohl(ofp11
) & 0xffff;
421 netdev_port_features_to_ofp11(enum netdev_features features
)
423 return htonl(features
& 0xffff);
427 ofputil_decode_ofp10_phy_port(struct ofputil_phy_port
*pp
,
428 const struct ofp10_phy_port
*opp
)
430 pp
->port_no
= u16_to_ofp(ntohs(opp
->port_no
));
431 pp
->hw_addr
= opp
->hw_addr
;
432 ovs_strlcpy_arrays(pp
->name
, opp
->name
);
434 pp
->config
= ntohl(opp
->config
) & OFPPC10_ALL
;
435 pp
->state
= ntohl(opp
->state
) & OFPPS10_ALL
;
437 pp
->curr
= netdev_port_features_from_ofp10(opp
->curr
);
438 pp
->advertised
= netdev_port_features_from_ofp10(opp
->advertised
);
439 pp
->supported
= netdev_port_features_from_ofp10(opp
->supported
);
440 pp
->peer
= netdev_port_features_from_ofp10(opp
->peer
);
442 pp
->curr_speed
= netdev_features_to_bps(pp
->curr
, 0) / 1000;
443 pp
->max_speed
= netdev_features_to_bps(pp
->supported
, 0) / 1000;
449 ofputil_decode_ofp11_port(struct ofputil_phy_port
*pp
,
450 const struct ofp11_port
*op
)
454 error
= ofputil_port_from_ofp11(op
->port_no
, &pp
->port_no
);
458 pp
->hw_addr
= op
->hw_addr
;
459 ovs_strlcpy_arrays(pp
->name
, op
->name
);
461 pp
->config
= ntohl(op
->config
) & OFPPC11_ALL
;
462 pp
->state
= ntohl(op
->state
) & OFPPS11_ALL
;
464 pp
->curr
= netdev_port_features_from_ofp11(op
->curr
);
465 pp
->advertised
= netdev_port_features_from_ofp11(op
->advertised
);
466 pp
->supported
= netdev_port_features_from_ofp11(op
->supported
);
467 pp
->peer
= netdev_port_features_from_ofp11(op
->peer
);
469 pp
->curr_speed
= ntohl(op
->curr_speed
);
470 pp
->max_speed
= ntohl(op
->max_speed
);
476 parse_ofp14_port_ethernet_property(const struct ofpbuf
*payload
,
477 struct ofputil_phy_port
*pp
)
479 struct ofp14_port_desc_prop_ethernet
*eth
= payload
->data
;
481 if (payload
->size
!= sizeof *eth
) {
482 return OFPERR_OFPBPC_BAD_LEN
;
485 pp
->curr
= netdev_port_features_from_ofp11(eth
->curr
);
486 pp
->advertised
= netdev_port_features_from_ofp11(eth
->advertised
);
487 pp
->supported
= netdev_port_features_from_ofp11(eth
->supported
);
488 pp
->peer
= netdev_port_features_from_ofp11(eth
->peer
);
490 pp
->curr_speed
= ntohl(eth
->curr_speed
);
491 pp
->max_speed
= ntohl(eth
->max_speed
);
497 ofputil_pull_ofp14_port_properties(const void *props
, size_t len
,
498 struct ofputil_phy_port
*pp
)
500 struct ofpbuf properties
= ofpbuf_const_initializer(props
, len
);
501 while (properties
.size
> 0) {
502 struct ofpbuf payload
;
506 error
= ofpprop_pull(&properties
, &payload
, &type
);
512 case OFPPDPT14_ETHERNET
:
513 error
= parse_ofp14_port_ethernet_property(&payload
, pp
);
517 error
= OFPPROP_UNKNOWN(true, "port", type
);
530 ofputil_pull_ofp14_port(struct ofputil_phy_port
*pp
, struct ofpbuf
*msg
)
532 const struct ofp14_port
*op
= ofpbuf_try_pull(msg
, sizeof *op
);
534 return OFPERR_OFPBRC_BAD_LEN
;
537 size_t len
= ntohs(op
->length
);
538 if (len
< sizeof *op
|| len
- sizeof *op
> msg
->size
) {
539 return OFPERR_OFPBRC_BAD_LEN
;
543 enum ofperr error
= ofputil_port_from_ofp11(op
->port_no
, &pp
->port_no
);
547 pp
->hw_addr
= op
->hw_addr
;
548 ovs_strlcpy_arrays(pp
->name
, op
->name
);
550 pp
->config
= ntohl(op
->config
) & OFPPC11_ALL
;
551 pp
->state
= ntohl(op
->state
) & OFPPS11_ALL
;
553 return ofputil_pull_ofp14_port_properties(ofpbuf_pull(msg
, len
), len
, pp
);
557 ofputil_encode_ofp10_phy_port(const struct ofputil_phy_port
*pp
,
558 struct ofp10_phy_port
*opp
)
560 memset(opp
, 0, sizeof *opp
);
562 opp
->port_no
= htons(ofp_to_u16(pp
->port_no
));
563 opp
->hw_addr
= pp
->hw_addr
;
564 ovs_strlcpy_arrays(opp
->name
, pp
->name
);
566 opp
->config
= htonl(pp
->config
& OFPPC10_ALL
);
567 opp
->state
= htonl(pp
->state
& OFPPS10_ALL
);
569 opp
->curr
= netdev_port_features_to_ofp10(pp
->curr
);
570 opp
->advertised
= netdev_port_features_to_ofp10(pp
->advertised
);
571 opp
->supported
= netdev_port_features_to_ofp10(pp
->supported
);
572 opp
->peer
= netdev_port_features_to_ofp10(pp
->peer
);
576 ofputil_encode_ofp11_port(const struct ofputil_phy_port
*pp
,
577 struct ofp11_port
*op
)
579 memset(op
, 0, sizeof *op
);
581 op
->port_no
= ofputil_port_to_ofp11(pp
->port_no
);
582 op
->hw_addr
= pp
->hw_addr
;
583 ovs_strlcpy_arrays(op
->name
, pp
->name
);
585 op
->config
= htonl(pp
->config
& OFPPC11_ALL
);
586 op
->state
= htonl(pp
->state
& OFPPS11_ALL
);
588 op
->curr
= netdev_port_features_to_ofp11(pp
->curr
);
589 op
->advertised
= netdev_port_features_to_ofp11(pp
->advertised
);
590 op
->supported
= netdev_port_features_to_ofp11(pp
->supported
);
591 op
->peer
= netdev_port_features_to_ofp11(pp
->peer
);
593 op
->curr_speed
= htonl(pp
->curr_speed
);
594 op
->max_speed
= htonl(pp
->max_speed
);
598 ofputil_encode_ofp14_port_ethernet_prop(
599 const struct ofputil_phy_port
*pp
,
600 struct ofp14_port_desc_prop_ethernet
*eth
)
602 eth
->curr
= netdev_port_features_to_ofp11(pp
->curr
);
603 eth
->advertised
= netdev_port_features_to_ofp11(pp
->advertised
);
604 eth
->supported
= netdev_port_features_to_ofp11(pp
->supported
);
605 eth
->peer
= netdev_port_features_to_ofp11(pp
->peer
);
606 eth
->curr_speed
= htonl(pp
->curr_speed
);
607 eth
->max_speed
= htonl(pp
->max_speed
);
611 ofputil_put_ofp14_port(const struct ofputil_phy_port
*pp
, struct ofpbuf
*b
)
613 struct ofp14_port
*op
;
614 struct ofp14_port_desc_prop_ethernet
*eth
;
616 ofpbuf_prealloc_tailroom(b
, sizeof *op
+ sizeof *eth
);
618 op
= ofpbuf_put_zeros(b
, sizeof *op
);
619 op
->port_no
= ofputil_port_to_ofp11(pp
->port_no
);
620 op
->length
= htons(sizeof *op
+ sizeof *eth
);
621 op
->hw_addr
= pp
->hw_addr
;
622 ovs_strlcpy_arrays(op
->name
, pp
->name
);
623 op
->config
= htonl(pp
->config
& OFPPC11_ALL
);
624 op
->state
= htonl(pp
->state
& OFPPS11_ALL
);
626 eth
= ofpprop_put_zeros(b
, OFPPDPT14_ETHERNET
, sizeof *eth
);
627 ofputil_encode_ofp14_port_ethernet_prop(pp
, eth
);
631 ofputil_put_phy_port(enum ofp_version ofp_version
,
632 const struct ofputil_phy_port
*pp
, struct ofpbuf
*b
)
634 switch (ofp_version
) {
635 case OFP10_VERSION
: {
636 struct ofp10_phy_port
*opp
= ofpbuf_put_uninit(b
, sizeof *opp
);
637 ofputil_encode_ofp10_phy_port(pp
, opp
);
643 case OFP13_VERSION
: {
644 struct ofp11_port
*op
= ofpbuf_put_uninit(b
, sizeof *op
);
645 ofputil_encode_ofp11_port(pp
, op
);
651 ofputil_put_ofp14_port(pp
, b
);
660 ofputil_decode_port_desc_stats_request(const struct ofp_header
*request
,
663 struct ofpbuf b
= ofpbuf_const_initializer(request
,
664 ntohs(request
->length
));
665 enum ofpraw raw
= ofpraw_pull_assert(&b
);
666 if (raw
== OFPRAW_OFPST10_PORT_DESC_REQUEST
) {
669 } else if (raw
== OFPRAW_OFPST15_PORT_DESC_REQUEST
) {
670 ovs_be32
*ofp11_port
;
672 ofp11_port
= ofpbuf_pull(&b
, sizeof *ofp11_port
);
673 return ofputil_port_from_ofp11(*ofp11_port
, port
);
680 ofputil_encode_port_desc_stats_request(enum ofp_version ofp_version
,
683 struct ofpbuf
*request
;
685 switch (ofp_version
) {
691 request
= ofpraw_alloc(OFPRAW_OFPST10_PORT_DESC_REQUEST
,
694 case OFP15_VERSION
: {
695 struct ofp15_port_desc_request
*req
;
696 request
= ofpraw_alloc(OFPRAW_OFPST15_PORT_DESC_REQUEST
,
698 req
= ofpbuf_put_zeros(request
, sizeof *req
);
699 req
->port_no
= ofputil_port_to_ofp11(port
);
710 ofputil_append_port_desc_stats_reply(const struct ofputil_phy_port
*pp
,
711 struct ovs_list
*replies
)
713 struct ofpbuf
*reply
= ofpbuf_from_list(ovs_list_back(replies
));
714 size_t start_ofs
= reply
->size
;
716 ofputil_put_phy_port(ofpmp_version(replies
), pp
, reply
);
717 ofpmp_postappend(replies
, start_ofs
);
720 /* Given a buffer 'b' that contains an array of OpenFlow ports of type
721 * 'ofp_version', tries to pull the first element from the array. If
722 * successful, initializes '*pp' with an abstract representation of the
723 * port and returns 0. If no ports remain to be decoded, returns EOF.
724 * On an error, returns a positive OFPERR_* value. */
726 ofputil_pull_phy_port(enum ofp_version ofp_version
, struct ofpbuf
*b
,
727 struct ofputil_phy_port
*pp
)
729 memset(pp
, 0, sizeof *pp
);
731 switch (ofp_version
) {
732 case OFP10_VERSION
: {
733 const struct ofp10_phy_port
*opp
= ofpbuf_try_pull(b
, sizeof *opp
);
734 return opp
? ofputil_decode_ofp10_phy_port(pp
, opp
) : EOF
;
738 case OFP13_VERSION
: {
739 const struct ofp11_port
*op
= ofpbuf_try_pull(b
, sizeof *op
);
740 return op
? ofputil_decode_ofp11_port(pp
, op
) : EOF
;
744 return b
->size
? ofputil_pull_ofp14_port(pp
, b
) : EOF
;
751 ofputil_phy_port_format(struct ds
*s
, const struct ofputil_phy_port
*port
)
753 char name
[sizeof port
->name
];
756 memcpy(name
, port
->name
, sizeof name
);
757 for (j
= 0; j
< sizeof name
- 1; j
++) {
758 if (!isprint((unsigned char) name
[j
])) {
765 ofputil_format_port(port
->port_no
, NULL
, s
);
766 ds_put_format(s
, "(%s): addr:"ETH_ADDR_FMT
"\n",
767 name
, ETH_ADDR_ARGS(port
->hw_addr
));
769 ds_put_cstr(s
, " config: ");
770 ofputil_port_config_format(s
, port
->config
);
772 ds_put_cstr(s
, " state: ");
773 ofputil_port_state_format(s
, port
->state
);
776 ds_put_format(s
, " current: ");
777 netdev_features_format(s
, port
->curr
);
779 if (port
->advertised
) {
780 ds_put_format(s
, " advertised: ");
781 netdev_features_format(s
, port
->advertised
);
783 if (port
->supported
) {
784 ds_put_format(s
, " supported: ");
785 netdev_features_format(s
, port
->supported
);
788 ds_put_format(s
, " peer: ");
789 netdev_features_format(s
, port
->peer
);
791 ds_put_format(s
, " speed: %"PRIu32
" Mbps now, "
792 "%"PRIu32
" Mbps max\n",
793 port
->curr_speed
/ UINT32_C(1000),
794 port
->max_speed
/ UINT32_C(1000));
797 /* qsort comparison function. */
799 compare_ports(const void *a_
, const void *b_
)
801 const struct ofputil_phy_port
*a
= a_
;
802 const struct ofputil_phy_port
*b
= b_
;
803 uint16_t ap
= ofp_to_u16(a
->port_no
);
804 uint16_t bp
= ofp_to_u16(b
->port_no
);
806 return ap
< bp
? -1 : ap
> bp
;
809 /* Given a buffer 'b' that contains an array of OpenFlow ports of type
810 * 'ofp_version', writes a detailed description of each port into 'string'. */
812 ofputil_phy_ports_format(struct ds
*string
, uint8_t ofp_version
,
815 struct ofputil_phy_port
*ports
;
816 size_t allocated_ports
, n_ports
;
822 for (n_ports
= 0; ; n_ports
++) {
823 if (n_ports
>= allocated_ports
) {
824 ports
= x2nrealloc(ports
, &allocated_ports
, sizeof *ports
);
827 retval
= ofputil_pull_phy_port(ofp_version
, b
, &ports
[n_ports
]);
833 qsort(ports
, n_ports
, sizeof *ports
, compare_ports
);
834 for (i
= 0; i
< n_ports
; i
++) {
835 ofputil_phy_port_format(string
, &ports
[i
]);
839 return retval
!= EOF
? retval
: 0;
842 /* ofputil_port_status */
844 /* Decodes the OpenFlow "port status" message in '*ops' into an abstract form
845 * in '*ps'. Returns 0 if successful, otherwise an OFPERR_* value. */
847 ofputil_decode_port_status(const struct ofp_header
*oh
,
848 struct ofputil_port_status
*ps
)
850 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
851 ofpraw_pull_assert(&b
);
853 const struct ofp_port_status
*ops
= ofpbuf_pull(&b
, sizeof *ops
);
854 if (ops
->reason
!= OFPPR_ADD
&&
855 ops
->reason
!= OFPPR_DELETE
&&
856 ops
->reason
!= OFPPR_MODIFY
) {
857 return OFPERR_NXBRC_BAD_REASON
;
859 ps
->reason
= ops
->reason
;
861 int retval
= ofputil_pull_phy_port(oh
->version
, &b
, &ps
->desc
);
862 ovs_assert(retval
!= EOF
);
866 /* Converts the abstract form of a "port status" message in '*ps' into an
867 * OpenFlow message suitable for 'protocol', and returns that encoded form in
868 * a buffer owned by the caller. */
870 ofputil_encode_port_status(const struct ofputil_port_status
*ps
,
871 enum ofputil_protocol protocol
)
873 struct ofp_port_status
*ops
;
875 enum ofp_version version
;
878 version
= ofputil_protocol_to_ofp_version(protocol
);
881 raw
= OFPRAW_OFPT10_PORT_STATUS
;
887 raw
= OFPRAW_OFPT11_PORT_STATUS
;
892 raw
= OFPRAW_OFPT14_PORT_STATUS
;
899 b
= ofpraw_alloc_xid(raw
, version
, htonl(0), 0);
900 ops
= ofpbuf_put_zeros(b
, sizeof *ops
);
901 ops
->reason
= ps
->reason
;
902 ofputil_put_phy_port(version
, &ps
->desc
, b
);
903 ofpmsg_update_length(b
);
908 ofputil_port_status_format(struct ds
*s
,
909 const struct ofputil_port_status
*ps
)
911 if (ps
->reason
== OFPPR_ADD
) {
912 ds_put_format(s
, " ADD:");
913 } else if (ps
->reason
== OFPPR_DELETE
) {
914 ds_put_format(s
, " DEL:");
915 } else if (ps
->reason
== OFPPR_MODIFY
) {
916 ds_put_format(s
, " MOD:");
919 ofputil_phy_port_format(s
, &ps
->desc
);
922 /* ofputil_port_mod */
925 parse_port_mod_ethernet_property(struct ofpbuf
*property
,
926 struct ofputil_port_mod
*pm
)
931 error
= ofpprop_parse_be32(property
, &advertise
);
933 pm
->advertise
= netdev_port_features_from_ofp11(advertise
);
939 ofputil_decode_ofp10_port_mod(const struct ofp10_port_mod
*opm
,
940 struct ofputil_port_mod
*pm
)
942 pm
->port_no
= u16_to_ofp(ntohs(opm
->port_no
));
943 pm
->hw_addr
= opm
->hw_addr
;
944 pm
->config
= ntohl(opm
->config
) & OFPPC10_ALL
;
945 pm
->mask
= ntohl(opm
->mask
) & OFPPC10_ALL
;
946 pm
->advertise
= netdev_port_features_from_ofp10(opm
->advertise
);
951 ofputil_decode_ofp11_port_mod(const struct ofp11_port_mod
*opm
,
952 struct ofputil_port_mod
*pm
)
956 error
= ofputil_port_from_ofp11(opm
->port_no
, &pm
->port_no
);
961 pm
->hw_addr
= opm
->hw_addr
;
962 pm
->config
= ntohl(opm
->config
) & OFPPC11_ALL
;
963 pm
->mask
= ntohl(opm
->mask
) & OFPPC11_ALL
;
964 pm
->advertise
= netdev_port_features_from_ofp11(opm
->advertise
);
970 ofputil_decode_ofp14_port_mod_properties(struct ofpbuf
*b
, bool loose
,
971 struct ofputil_port_mod
*pm
)
973 while (b
->size
> 0) {
974 struct ofpbuf property
;
978 error
= ofpprop_pull(b
, &property
, &type
);
984 case OFPPMPT14_ETHERNET
:
985 error
= parse_port_mod_ethernet_property(&property
, pm
);
989 error
= OFPPROP_UNKNOWN(loose
, "port_mod", type
);
1001 ofputil_decode_ofp14_port_mod(struct ofpbuf
*b
, bool loose
,
1002 struct ofputil_port_mod
*pm
)
1004 const struct ofp14_port_mod
*opm
= ofpbuf_pull(b
, sizeof *opm
);
1005 enum ofperr error
= ofputil_port_from_ofp11(opm
->port_no
, &pm
->port_no
);
1010 pm
->hw_addr
= opm
->hw_addr
;
1011 pm
->config
= ntohl(opm
->config
) & OFPPC11_ALL
;
1012 pm
->mask
= ntohl(opm
->mask
) & OFPPC11_ALL
;
1014 return ofputil_decode_ofp14_port_mod_properties(b
, loose
, pm
);
1017 /* Decodes the OpenFlow "port mod" message in '*oh' into an abstract form in
1018 * '*pm'. Returns 0 if successful, otherwise an OFPERR_* value. */
1020 ofputil_decode_port_mod(const struct ofp_header
*oh
,
1021 struct ofputil_port_mod
*pm
, bool loose
)
1023 memset(pm
, 0, sizeof *pm
);
1025 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
1026 enum ofpraw raw
= ofpraw_pull_assert(&b
);
1029 if (raw
== OFPRAW_OFPT10_PORT_MOD
) {
1030 error
= ofputil_decode_ofp10_port_mod(b
.data
, pm
);
1031 } else if (raw
== OFPRAW_OFPT11_PORT_MOD
) {
1032 error
= ofputil_decode_ofp11_port_mod(b
.data
, pm
);
1033 } else if (raw
== OFPRAW_OFPT14_PORT_MOD
) {
1034 error
= ofputil_decode_ofp14_port_mod(&b
, loose
, pm
);
1036 error
= OFPERR_OFPBRC_BAD_TYPE
;
1039 pm
->config
&= pm
->mask
;
1043 /* Converts the abstract form of a "port mod" message in '*pm' into an OpenFlow
1044 * message suitable for 'protocol', and returns that encoded form in a buffer
1045 * owned by the caller. */
1047 ofputil_encode_port_mod(const struct ofputil_port_mod
*pm
,
1048 enum ofputil_protocol protocol
)
1050 enum ofp_version ofp_version
= ofputil_protocol_to_ofp_version(protocol
);
1053 switch (ofp_version
) {
1054 case OFP10_VERSION
: {
1055 struct ofp10_port_mod
*opm
;
1057 b
= ofpraw_alloc(OFPRAW_OFPT10_PORT_MOD
, ofp_version
, 0);
1058 opm
= ofpbuf_put_zeros(b
, sizeof *opm
);
1059 opm
->port_no
= htons(ofp_to_u16(pm
->port_no
));
1060 opm
->hw_addr
= pm
->hw_addr
;
1061 opm
->config
= htonl(pm
->config
& OFPPC10_ALL
);
1062 opm
->mask
= htonl(pm
->mask
& OFPPC10_ALL
);
1063 opm
->advertise
= netdev_port_features_to_ofp10(pm
->advertise
);
1069 case OFP13_VERSION
: {
1070 struct ofp11_port_mod
*opm
;
1072 b
= ofpraw_alloc(OFPRAW_OFPT11_PORT_MOD
, ofp_version
, 0);
1073 opm
= ofpbuf_put_zeros(b
, sizeof *opm
);
1074 opm
->port_no
= ofputil_port_to_ofp11(pm
->port_no
);
1075 opm
->hw_addr
= pm
->hw_addr
;
1076 opm
->config
= htonl(pm
->config
& OFPPC11_ALL
);
1077 opm
->mask
= htonl(pm
->mask
& OFPPC11_ALL
);
1078 opm
->advertise
= netdev_port_features_to_ofp11(pm
->advertise
);
1082 case OFP15_VERSION
: {
1083 struct ofp14_port_mod
*opm
;
1085 b
= ofpraw_alloc(OFPRAW_OFPT14_PORT_MOD
, ofp_version
, 0);
1086 opm
= ofpbuf_put_zeros(b
, sizeof *opm
);
1087 opm
->port_no
= ofputil_port_to_ofp11(pm
->port_no
);
1088 opm
->hw_addr
= pm
->hw_addr
;
1089 opm
->config
= htonl(pm
->config
& OFPPC11_ALL
);
1090 opm
->mask
= htonl(pm
->mask
& OFPPC11_ALL
);
1092 if (pm
->advertise
) {
1093 ofpprop_put_be32(b
, OFPPMPT14_ETHERNET
,
1094 netdev_port_features_to_ofp11(pm
->advertise
));
1106 ofputil_port_mod_format(struct ds
*s
, const struct ofputil_port_mod
*pm
,
1107 const struct ofputil_port_map
*port_map
)
1109 ds_put_cstr(s
, " port: ");
1110 ofputil_format_port(pm
->port_no
, port_map
, s
);
1111 ds_put_format(s
, ": addr:"ETH_ADDR_FMT
"\n",
1112 ETH_ADDR_ARGS(pm
->hw_addr
));
1114 ds_put_cstr(s
, " config: ");
1115 ofputil_port_config_format(s
, pm
->config
);
1117 ds_put_cstr(s
, " mask: ");
1118 ofputil_port_config_format(s
, pm
->mask
);
1120 ds_put_cstr(s
, " advertise: ");
1121 if (pm
->advertise
) {
1122 netdev_features_format(s
, pm
->advertise
);
1124 ds_put_cstr(s
, "UNCHANGED\n");
1128 /* Encode a dump ports request for 'port', the encoded message
1129 * will be for OpenFlow version 'ofp_version'. Returns message
1130 * as a struct ofpbuf. Returns encoded message on success, NULL on error */
1132 ofputil_encode_dump_ports_request(enum ofp_version ofp_version
,
1135 struct ofpbuf
*request
;
1137 switch (ofp_version
) {
1138 case OFP10_VERSION
: {
1139 struct ofp10_port_stats_request
*req
;
1140 request
= ofpraw_alloc(OFPRAW_OFPST10_PORT_REQUEST
, ofp_version
, 0);
1141 req
= ofpbuf_put_zeros(request
, sizeof *req
);
1142 req
->port_no
= htons(ofp_to_u16(port
));
1149 case OFP15_VERSION
: {
1150 struct ofp11_port_stats_request
*req
;
1151 request
= ofpraw_alloc(OFPRAW_OFPST11_PORT_REQUEST
, ofp_version
, 0);
1152 req
= ofpbuf_put_zeros(request
, sizeof *req
);
1153 req
->port_no
= ofputil_port_to_ofp11(port
);
1164 ofputil_port_stats_to_ofp10(const struct ofputil_port_stats
*ops
,
1165 struct ofp10_port_stats
*ps10
)
1167 ps10
->port_no
= htons(ofp_to_u16(ops
->port_no
));
1168 memset(ps10
->pad
, 0, sizeof ps10
->pad
);
1169 put_32aligned_be64(&ps10
->rx_packets
, htonll(ops
->stats
.rx_packets
));
1170 put_32aligned_be64(&ps10
->tx_packets
, htonll(ops
->stats
.tx_packets
));
1171 put_32aligned_be64(&ps10
->rx_bytes
, htonll(ops
->stats
.rx_bytes
));
1172 put_32aligned_be64(&ps10
->tx_bytes
, htonll(ops
->stats
.tx_bytes
));
1173 put_32aligned_be64(&ps10
->rx_dropped
, htonll(ops
->stats
.rx_dropped
));
1174 put_32aligned_be64(&ps10
->tx_dropped
, htonll(ops
->stats
.tx_dropped
));
1175 put_32aligned_be64(&ps10
->rx_errors
, htonll(ops
->stats
.rx_errors
));
1176 put_32aligned_be64(&ps10
->tx_errors
, htonll(ops
->stats
.tx_errors
));
1177 put_32aligned_be64(&ps10
->rx_frame_err
,
1178 htonll(ops
->stats
.rx_frame_errors
));
1179 put_32aligned_be64(&ps10
->rx_over_err
, htonll(ops
->stats
.rx_over_errors
));
1180 put_32aligned_be64(&ps10
->rx_crc_err
, htonll(ops
->stats
.rx_crc_errors
));
1181 put_32aligned_be64(&ps10
->collisions
, htonll(ops
->stats
.collisions
));
1185 ofputil_port_stats_to_ofp11(const struct ofputil_port_stats
*ops
,
1186 struct ofp11_port_stats
*ps11
)
1188 ps11
->port_no
= ofputil_port_to_ofp11(ops
->port_no
);
1189 memset(ps11
->pad
, 0, sizeof ps11
->pad
);
1190 ps11
->rx_packets
= htonll(ops
->stats
.rx_packets
);
1191 ps11
->tx_packets
= htonll(ops
->stats
.tx_packets
);
1192 ps11
->rx_bytes
= htonll(ops
->stats
.rx_bytes
);
1193 ps11
->tx_bytes
= htonll(ops
->stats
.tx_bytes
);
1194 ps11
->rx_dropped
= htonll(ops
->stats
.rx_dropped
);
1195 ps11
->tx_dropped
= htonll(ops
->stats
.tx_dropped
);
1196 ps11
->rx_errors
= htonll(ops
->stats
.rx_errors
);
1197 ps11
->tx_errors
= htonll(ops
->stats
.tx_errors
);
1198 ps11
->rx_frame_err
= htonll(ops
->stats
.rx_frame_errors
);
1199 ps11
->rx_over_err
= htonll(ops
->stats
.rx_over_errors
);
1200 ps11
->rx_crc_err
= htonll(ops
->stats
.rx_crc_errors
);
1201 ps11
->collisions
= htonll(ops
->stats
.collisions
);
1205 ofputil_port_stats_to_ofp13(const struct ofputil_port_stats
*ops
,
1206 struct ofp13_port_stats
*ps13
)
1208 ofputil_port_stats_to_ofp11(ops
, &ps13
->ps
);
1209 ps13
->duration_sec
= htonl(ops
->duration_sec
);
1210 ps13
->duration_nsec
= htonl(ops
->duration_nsec
);
1214 ofputil_append_ofp14_port_stats(const struct ofputil_port_stats
*ops
,
1215 struct ovs_list
*replies
)
1217 struct ofp14_port_stats_prop_ethernet
*eth
;
1218 struct intel_port_stats_rfc2819
*stats_rfc2819
;
1219 struct intel_port_custom_stats
*stats_custom
;
1220 struct ofp14_port_stats
*ps14
;
1221 struct ofpbuf
*reply
;
1223 ovs_be64 counter_value
;
1224 size_t custom_stats_start
, start_ofs
;
1226 reply
= ofpbuf_from_list(ovs_list_back(replies
));
1227 start_ofs
= reply
->size
;
1229 ps14
= ofpbuf_put_uninit(reply
, sizeof *ps14
);
1231 memset(ps14
->pad
, 0, sizeof ps14
->pad
);
1232 ps14
->port_no
= ofputil_port_to_ofp11(ops
->port_no
);
1233 ps14
->duration_sec
= htonl(ops
->duration_sec
);
1234 ps14
->duration_nsec
= htonl(ops
->duration_nsec
);
1235 ps14
->rx_packets
= htonll(ops
->stats
.rx_packets
);
1236 ps14
->tx_packets
= htonll(ops
->stats
.tx_packets
);
1237 ps14
->rx_bytes
= htonll(ops
->stats
.rx_bytes
);
1238 ps14
->tx_bytes
= htonll(ops
->stats
.tx_bytes
);
1239 ps14
->rx_dropped
= htonll(ops
->stats
.rx_dropped
);
1240 ps14
->tx_dropped
= htonll(ops
->stats
.tx_dropped
);
1241 ps14
->rx_errors
= htonll(ops
->stats
.rx_errors
);
1242 ps14
->tx_errors
= htonll(ops
->stats
.tx_errors
);
1244 eth
= ofpprop_put_zeros(reply
, OFPPSPT14_ETHERNET
, sizeof *eth
);
1245 eth
->rx_frame_err
= htonll(ops
->stats
.rx_frame_errors
);
1246 eth
->rx_over_err
= htonll(ops
->stats
.rx_over_errors
);
1247 eth
->rx_crc_err
= htonll(ops
->stats
.rx_crc_errors
);
1248 eth
->collisions
= htonll(ops
->stats
.collisions
);
1250 uint64_t prop_type_stats
= OFPPROP_EXP(INTEL_VENDOR_ID
,
1251 INTEL_PORT_STATS_RFC2819
);
1253 stats_rfc2819
= ofpprop_put_zeros(reply
, prop_type_stats
,
1254 sizeof *stats_rfc2819
);
1256 memset(stats_rfc2819
->pad
, 0, sizeof stats_rfc2819
->pad
);
1257 stats_rfc2819
->rx_1_to_64_packets
= htonll(ops
->stats
.rx_1_to_64_packets
);
1258 stats_rfc2819
->rx_65_to_127_packets
=
1259 htonll(ops
->stats
.rx_65_to_127_packets
);
1260 stats_rfc2819
->rx_128_to_255_packets
=
1261 htonll(ops
->stats
.rx_128_to_255_packets
);
1262 stats_rfc2819
->rx_256_to_511_packets
=
1263 htonll(ops
->stats
.rx_256_to_511_packets
);
1264 stats_rfc2819
->rx_512_to_1023_packets
=
1265 htonll(ops
->stats
.rx_512_to_1023_packets
);
1266 stats_rfc2819
->rx_1024_to_1522_packets
=
1267 htonll(ops
->stats
.rx_1024_to_1522_packets
);
1268 stats_rfc2819
->rx_1523_to_max_packets
=
1269 htonll(ops
->stats
.rx_1523_to_max_packets
);
1271 stats_rfc2819
->tx_1_to_64_packets
= htonll(ops
->stats
.tx_1_to_64_packets
);
1272 stats_rfc2819
->tx_65_to_127_packets
=
1273 htonll(ops
->stats
.tx_65_to_127_packets
);
1274 stats_rfc2819
->tx_128_to_255_packets
=
1275 htonll(ops
->stats
.tx_128_to_255_packets
);
1276 stats_rfc2819
->tx_256_to_511_packets
=
1277 htonll(ops
->stats
.tx_256_to_511_packets
);
1278 stats_rfc2819
->tx_512_to_1023_packets
=
1279 htonll(ops
->stats
.tx_512_to_1023_packets
);
1280 stats_rfc2819
->tx_1024_to_1522_packets
=
1281 htonll(ops
->stats
.tx_1024_to_1522_packets
);
1282 stats_rfc2819
->tx_1523_to_max_packets
=
1283 htonll(ops
->stats
.tx_1523_to_max_packets
);
1285 stats_rfc2819
->tx_multicast_packets
=
1286 htonll(ops
->stats
.tx_multicast_packets
);
1287 stats_rfc2819
->rx_broadcast_packets
=
1288 htonll(ops
->stats
.rx_broadcast_packets
);
1289 stats_rfc2819
->tx_broadcast_packets
=
1290 htonll(ops
->stats
.tx_broadcast_packets
);
1291 stats_rfc2819
->rx_undersized_errors
=
1292 htonll(ops
->stats
.rx_undersized_errors
);
1293 stats_rfc2819
->rx_oversize_errors
=
1294 htonll(ops
->stats
.rx_oversize_errors
);
1295 stats_rfc2819
->rx_fragmented_errors
=
1296 htonll(ops
->stats
.rx_fragmented_errors
);
1297 stats_rfc2819
->rx_jabber_errors
=
1298 htonll(ops
->stats
.rx_jabber_errors
);
1300 if (ops
->custom_stats
.counters
&& ops
->custom_stats
.size
) {
1301 custom_stats_start
= reply
->size
;
1303 uint64_t prop_type_custom
= OFPPROP_EXP(INTEL_VENDOR_ID
,
1304 INTEL_PORT_STATS_CUSTOM
);
1306 stats_custom
= ofpprop_put_zeros(reply
, prop_type_custom
,
1307 sizeof *stats_custom
);
1309 stats_custom
->stats_array_size
= htons(ops
->custom_stats
.size
);
1311 for (i
= 0; i
< ops
->custom_stats
.size
; i
++) {
1312 uint8_t counter_size
= strlen(ops
->custom_stats
.counters
[i
].name
);
1313 /* Counter name size */
1314 ofpbuf_put(reply
, &counter_size
, sizeof(counter_size
));
1316 ofpbuf_put(reply
, ops
->custom_stats
.counters
[i
].name
,
1319 counter_value
= htonll(ops
->custom_stats
.counters
[i
].value
);
1320 ofpbuf_put(reply
, &counter_value
,
1321 sizeof(ops
->custom_stats
.counters
[i
].value
));
1324 ofpprop_end(reply
, custom_stats_start
);
1327 ps14
= ofpbuf_at_assert(reply
, start_ofs
, sizeof *ps14
);
1328 ps14
->length
= htons(reply
->size
- start_ofs
);
1330 ofpmp_postappend(replies
, start_ofs
);
1333 /* Encode a ports stat for 'ops' and append it to 'replies'. */
1335 ofputil_append_port_stat(struct ovs_list
*replies
,
1336 const struct ofputil_port_stats
*ops
)
1338 switch (ofpmp_version(replies
)) {
1339 case OFP13_VERSION
: {
1340 struct ofp13_port_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
1341 ofputil_port_stats_to_ofp13(ops
, reply
);
1345 case OFP11_VERSION
: {
1346 struct ofp11_port_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
1347 ofputil_port_stats_to_ofp11(ops
, reply
);
1351 case OFP10_VERSION
: {
1352 struct ofp10_port_stats
*reply
= ofpmp_append(replies
, sizeof *reply
);
1353 ofputil_port_stats_to_ofp10(ops
, reply
);
1359 ofputil_append_ofp14_port_stats(ops
, replies
);
1368 ofputil_port_stats_from_ofp10(struct ofputil_port_stats
*ops
,
1369 const struct ofp10_port_stats
*ps10
)
1372 ops
->port_no
= u16_to_ofp(ntohs(ps10
->port_no
));
1373 ops
->stats
.rx_packets
= ntohll(get_32aligned_be64(&ps10
->rx_packets
));
1374 ops
->stats
.tx_packets
= ntohll(get_32aligned_be64(&ps10
->tx_packets
));
1375 ops
->stats
.rx_bytes
= ntohll(get_32aligned_be64(&ps10
->rx_bytes
));
1376 ops
->stats
.tx_bytes
= ntohll(get_32aligned_be64(&ps10
->tx_bytes
));
1377 ops
->stats
.rx_dropped
= ntohll(get_32aligned_be64(&ps10
->rx_dropped
));
1378 ops
->stats
.tx_dropped
= ntohll(get_32aligned_be64(&ps10
->tx_dropped
));
1379 ops
->stats
.rx_errors
= ntohll(get_32aligned_be64(&ps10
->rx_errors
));
1380 ops
->stats
.tx_errors
= ntohll(get_32aligned_be64(&ps10
->tx_errors
));
1381 ops
->stats
.rx_frame_errors
=
1382 ntohll(get_32aligned_be64(&ps10
->rx_frame_err
));
1383 ops
->stats
.rx_over_errors
= ntohll(get_32aligned_be64(&ps10
->rx_over_err
));
1384 ops
->stats
.rx_crc_errors
= ntohll(get_32aligned_be64(&ps10
->rx_crc_err
));
1385 ops
->stats
.collisions
= ntohll(get_32aligned_be64(&ps10
->collisions
));
1386 ops
->duration_sec
= ops
->duration_nsec
= UINT32_MAX
;
1392 ofputil_port_stats_from_ofp11(struct ofputil_port_stats
*ops
,
1393 const struct ofp11_port_stats
*ps11
)
1397 error
= ofputil_port_from_ofp11(ps11
->port_no
, &ops
->port_no
);
1402 ops
->stats
.rx_packets
= ntohll(ps11
->rx_packets
);
1403 ops
->stats
.tx_packets
= ntohll(ps11
->tx_packets
);
1404 ops
->stats
.rx_bytes
= ntohll(ps11
->rx_bytes
);
1405 ops
->stats
.tx_bytes
= ntohll(ps11
->tx_bytes
);
1406 ops
->stats
.rx_dropped
= ntohll(ps11
->rx_dropped
);
1407 ops
->stats
.tx_dropped
= ntohll(ps11
->tx_dropped
);
1408 ops
->stats
.rx_errors
= ntohll(ps11
->rx_errors
);
1409 ops
->stats
.tx_errors
= ntohll(ps11
->tx_errors
);
1410 ops
->stats
.rx_frame_errors
= ntohll(ps11
->rx_frame_err
);
1411 ops
->stats
.rx_over_errors
= ntohll(ps11
->rx_over_err
);
1412 ops
->stats
.rx_crc_errors
= ntohll(ps11
->rx_crc_err
);
1413 ops
->stats
.collisions
= ntohll(ps11
->collisions
);
1414 ops
->duration_sec
= ops
->duration_nsec
= UINT32_MAX
;
1420 ofputil_port_stats_from_ofp13(struct ofputil_port_stats
*ops
,
1421 const struct ofp13_port_stats
*ps13
)
1423 enum ofperr error
= ofputil_port_stats_from_ofp11(ops
, &ps13
->ps
);
1425 ops
->duration_sec
= ntohl(ps13
->duration_sec
);
1426 ops
->duration_nsec
= ntohl(ps13
->duration_nsec
);
1432 parse_ofp14_port_stats_ethernet_property(const struct ofpbuf
*payload
,
1433 struct ofputil_port_stats
*ops
)
1435 const struct ofp14_port_stats_prop_ethernet
*eth
= payload
->data
;
1437 if (payload
->size
!= sizeof *eth
) {
1438 return OFPERR_OFPBPC_BAD_LEN
;
1441 ops
->stats
.rx_frame_errors
= ntohll(eth
->rx_frame_err
);
1442 ops
->stats
.rx_over_errors
= ntohll(eth
->rx_over_err
);
1443 ops
->stats
.rx_crc_errors
= ntohll(eth
->rx_crc_err
);
1444 ops
->stats
.collisions
= ntohll(eth
->collisions
);
1450 parse_intel_port_stats_rfc2819_property(const struct ofpbuf
*payload
,
1451 struct ofputil_port_stats
*ops
)
1453 const struct intel_port_stats_rfc2819
*rfc2819
= payload
->data
;
1455 if (payload
->size
!= sizeof *rfc2819
) {
1456 return OFPERR_OFPBPC_BAD_LEN
;
1458 ops
->stats
.rx_1_to_64_packets
= ntohll(rfc2819
->rx_1_to_64_packets
);
1459 ops
->stats
.rx_65_to_127_packets
= ntohll(rfc2819
->rx_65_to_127_packets
);
1460 ops
->stats
.rx_128_to_255_packets
= ntohll(rfc2819
->rx_128_to_255_packets
);
1461 ops
->stats
.rx_256_to_511_packets
= ntohll(rfc2819
->rx_256_to_511_packets
);
1462 ops
->stats
.rx_512_to_1023_packets
=
1463 ntohll(rfc2819
->rx_512_to_1023_packets
);
1464 ops
->stats
.rx_1024_to_1522_packets
=
1465 ntohll(rfc2819
->rx_1024_to_1522_packets
);
1466 ops
->stats
.rx_1523_to_max_packets
=
1467 ntohll(rfc2819
->rx_1523_to_max_packets
);
1469 ops
->stats
.tx_1_to_64_packets
= ntohll(rfc2819
->tx_1_to_64_packets
);
1470 ops
->stats
.tx_65_to_127_packets
= ntohll(rfc2819
->tx_65_to_127_packets
);
1471 ops
->stats
.tx_128_to_255_packets
= ntohll(rfc2819
->tx_128_to_255_packets
);
1472 ops
->stats
.tx_256_to_511_packets
= ntohll(rfc2819
->tx_256_to_511_packets
);
1473 ops
->stats
.tx_512_to_1023_packets
=
1474 ntohll(rfc2819
->tx_512_to_1023_packets
);
1475 ops
->stats
.tx_1024_to_1522_packets
=
1476 ntohll(rfc2819
->tx_1024_to_1522_packets
);
1477 ops
->stats
.tx_1523_to_max_packets
=
1478 ntohll(rfc2819
->tx_1523_to_max_packets
);
1480 ops
->stats
.tx_multicast_packets
= ntohll(rfc2819
->tx_multicast_packets
);
1481 ops
->stats
.rx_broadcast_packets
= ntohll(rfc2819
->rx_broadcast_packets
);
1482 ops
->stats
.tx_broadcast_packets
= ntohll(rfc2819
->tx_broadcast_packets
);
1483 ops
->stats
.rx_undersized_errors
= ntohll(rfc2819
->rx_undersized_errors
);
1485 ops
->stats
.rx_oversize_errors
= ntohll(rfc2819
->rx_oversize_errors
);
1486 ops
->stats
.rx_fragmented_errors
= ntohll(rfc2819
->rx_fragmented_errors
);
1487 ops
->stats
.rx_jabber_errors
= ntohll(rfc2819
->rx_jabber_errors
);
1493 parse_intel_port_custom_property(struct ofpbuf
*payload
,
1494 struct ofputil_port_stats
*ops
)
1496 const struct intel_port_custom_stats
*custom_stats
1497 = ofpbuf_try_pull(payload
, sizeof *custom_stats
);
1498 if (!custom_stats
) {
1499 return OFPERR_OFPBPC_BAD_LEN
;
1502 ops
->custom_stats
.size
= ntohs(custom_stats
->stats_array_size
);
1504 netdev_free_custom_stats_counters(&ops
->custom_stats
);
1505 ops
->custom_stats
.counters
= xcalloc(ops
->custom_stats
.size
,
1506 sizeof *ops
->custom_stats
.counters
);
1508 for (int i
= 0; i
< ops
->custom_stats
.size
; i
++) {
1509 struct netdev_custom_counter
*c
= &ops
->custom_stats
.counters
[i
];
1512 uint8_t *name_len
= ofpbuf_try_pull(payload
, sizeof *name_len
);
1513 char *name
= name_len
? ofpbuf_try_pull(payload
, *name_len
) : NULL
;
1514 if (!name_len
|| !name
) {
1515 netdev_free_custom_stats_counters(&ops
->custom_stats
);
1516 return OFPERR_OFPBPC_BAD_LEN
;
1519 size_t len
= MIN(*name_len
, sizeof c
->name
- 1);
1520 memcpy(c
->name
, name
, len
);
1521 c
->name
[len
] = '\0';
1523 /* Counter value. */
1524 ovs_be64
*value
= ofpbuf_try_pull(payload
, sizeof *value
);
1526 netdev_free_custom_stats_counters(&ops
->custom_stats
);
1527 return OFPERR_OFPBPC_BAD_LEN
;
1529 c
->value
= ntohll(get_unaligned_be64(value
));
1536 ofputil_pull_ofp14_port_stats(struct ofputil_port_stats
*ops
,
1539 const struct ofp14_port_stats
*ps14
= ofpbuf_try_pull(msg
, sizeof *ps14
);
1541 return OFPERR_OFPBRC_BAD_LEN
;
1544 size_t len
= ntohs(ps14
->length
);
1545 if (len
< sizeof *ps14
|| len
- sizeof *ps14
> msg
->size
) {
1546 return OFPERR_OFPBRC_BAD_LEN
;
1548 len
-= sizeof *ps14
;
1550 enum ofperr error
= ofputil_port_from_ofp11(ps14
->port_no
, &ops
->port_no
);
1555 ops
->duration_sec
= ntohl(ps14
->duration_sec
);
1556 ops
->duration_nsec
= ntohl(ps14
->duration_nsec
);
1557 ops
->stats
.rx_packets
= ntohll(ps14
->rx_packets
);
1558 ops
->stats
.tx_packets
= ntohll(ps14
->tx_packets
);
1559 ops
->stats
.rx_bytes
= ntohll(ps14
->rx_bytes
);
1560 ops
->stats
.tx_bytes
= ntohll(ps14
->tx_bytes
);
1561 ops
->stats
.rx_dropped
= ntohll(ps14
->rx_dropped
);
1562 ops
->stats
.tx_dropped
= ntohll(ps14
->tx_dropped
);
1563 ops
->stats
.rx_errors
= ntohll(ps14
->rx_errors
);
1564 ops
->stats
.tx_errors
= ntohll(ps14
->tx_errors
);
1567 struct ofpbuf properties
= ofpbuf_const_initializer(ofpbuf_pull(msg
, len
),
1569 while (properties
.size
> 0) {
1570 struct ofpbuf payload
;
1573 error
= ofpprop_pull(&properties
, &payload
, &type
);
1575 netdev_free_custom_stats_counters(&ops
->custom_stats
);
1579 case OFPPSPT14_ETHERNET
:
1580 error
= parse_ofp14_port_stats_ethernet_property(&payload
, ops
);
1582 case OFPPROP_EXP(INTEL_VENDOR_ID
, INTEL_PORT_STATS_RFC2819
):
1583 error
= parse_intel_port_stats_rfc2819_property(&payload
, ops
);
1585 case OFPPROP_EXP(INTEL_VENDOR_ID
, INTEL_PORT_STATS_CUSTOM
):
1586 error
= parse_intel_port_custom_property(&payload
, ops
);
1589 error
= OFPPROP_UNKNOWN(true, "port stats", type
);
1594 netdev_free_custom_stats_counters(&ops
->custom_stats
);
1602 /* Returns the number of port stats elements in OFPTYPE_PORT_STATS_REPLY
1605 ofputil_count_port_stats(const struct ofp_header
*oh
)
1607 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
1608 ofpraw_pull_assert(&b
);
1610 for (size_t n
= 0; ; n
++) {
1611 struct ofputil_port_stats ps
;
1612 if (ofputil_decode_port_stats(&ps
, &b
)) {
1615 netdev_free_custom_stats_counters(&ps
.custom_stats
);
1619 /* Converts an OFPST_PORT_STATS reply in 'msg' into an abstract
1620 * ofputil_port_stats in 'ps'.
1622 * Multiple OFPST_PORT_STATS replies can be packed into a single OpenFlow
1623 * message. Calling this function multiple times for a single 'msg' iterates
1624 * through the replies. The caller must initially leave 'msg''s layer pointers
1625 * null and not modify them between calls.
1627 * Returns 0 if successful, EOF if no replies were left in this 'msg',
1628 * otherwise a positive errno value.
1630 * On success, the caller must eventually free ps->custom_stats.counters,
1631 * with netdev_free_custom_stats_counters(&ps->custom_stats). */
1633 ofputil_decode_port_stats(struct ofputil_port_stats
*ps
, struct ofpbuf
*msg
)
1638 memset(&(ps
->stats
), 0xFF, sizeof (ps
->stats
));
1639 memset(&(ps
->custom_stats
), 0, sizeof (ps
->custom_stats
));
1641 error
= (msg
->header
? ofpraw_decode(&raw
, msg
->header
)
1642 : ofpraw_pull(&raw
, msg
));
1649 } else if (raw
== OFPRAW_OFPST14_PORT_REPLY
) {
1650 return ofputil_pull_ofp14_port_stats(ps
, msg
);
1651 } else if (raw
== OFPRAW_OFPST13_PORT_REPLY
) {
1652 const struct ofp13_port_stats
*ps13
;
1653 ps13
= ofpbuf_try_pull(msg
, sizeof *ps13
);
1657 return ofputil_port_stats_from_ofp13(ps
, ps13
);
1658 } else if (raw
== OFPRAW_OFPST11_PORT_REPLY
) {
1659 const struct ofp11_port_stats
*ps11
;
1661 ps11
= ofpbuf_try_pull(msg
, sizeof *ps11
);
1665 return ofputil_port_stats_from_ofp11(ps
, ps11
);
1666 } else if (raw
== OFPRAW_OFPST10_PORT_REPLY
) {
1667 const struct ofp10_port_stats
*ps10
;
1669 ps10
= ofpbuf_try_pull(msg
, sizeof *ps10
);
1673 return ofputil_port_stats_from_ofp10(ps
, ps10
);
1679 VLOG_WARN_RL(&rl
, "OFPST_PORT reply has %"PRIu32
" leftover "
1680 "bytes at end", msg
->size
);
1681 return OFPERR_OFPBRC_BAD_LEN
;
1685 print_port_stat(struct ds
*string
, const char *leader
, uint64_t stat
, int more
)
1687 ds_put_cstr(string
, leader
);
1688 if (stat
!= UINT64_MAX
) {
1689 ds_put_format(string
, "%"PRIu64
, stat
);
1691 ds_put_char(string
, '?');
1694 ds_put_cstr(string
, ", ");
1696 ds_put_cstr(string
, "\n");
1701 print_port_stat_cond(struct ds
*string
, const char *leader
, uint64_t stat
)
1703 if (stat
!= UINT64_MAX
) {
1704 ds_put_format(string
, "%s%"PRIu64
", ", leader
, stat
);
1709 ofputil_format_port_stats(struct ds
*string
,
1710 const struct ofputil_port_stats
*ps
,
1711 const struct ofputil_port_map
*port_map
)
1713 ds_put_cstr(string
, " port ");
1714 if (ofp_to_u16(ps
->port_no
) < 10) {
1715 ds_put_char(string
, ' ');
1717 ofputil_format_port(ps
->port_no
, port_map
, string
);
1719 ds_put_cstr(string
, ": rx ");
1720 print_port_stat(string
, "pkts=", ps
->stats
.rx_packets
, 1);
1721 print_port_stat(string
, "bytes=", ps
->stats
.rx_bytes
, 1);
1722 print_port_stat(string
, "drop=", ps
->stats
.rx_dropped
, 1);
1723 print_port_stat(string
, "errs=", ps
->stats
.rx_errors
, 1);
1724 print_port_stat(string
, "frame=", ps
->stats
.rx_frame_errors
, 1);
1725 print_port_stat(string
, "over=", ps
->stats
.rx_over_errors
, 1);
1726 print_port_stat(string
, "crc=", ps
->stats
.rx_crc_errors
, 0);
1728 ds_put_cstr(string
, " tx ");
1729 print_port_stat(string
, "pkts=", ps
->stats
.tx_packets
, 1);
1730 print_port_stat(string
, "bytes=", ps
->stats
.tx_bytes
, 1);
1731 print_port_stat(string
, "drop=", ps
->stats
.tx_dropped
, 1);
1732 print_port_stat(string
, "errs=", ps
->stats
.tx_errors
, 1);
1733 print_port_stat(string
, "coll=", ps
->stats
.collisions
, 0);
1735 if (ps
->duration_sec
!= UINT32_MAX
) {
1736 ds_put_cstr(string
, " duration=");
1737 ofp_print_duration(string
, ps
->duration_sec
, ps
->duration_nsec
);
1738 ds_put_char(string
, '\n');
1740 struct ds string_ext_stats
= DS_EMPTY_INITIALIZER
;
1742 ds_init(&string_ext_stats
);
1744 print_port_stat_cond(&string_ext_stats
, "1_to_64_packets=",
1745 ps
->stats
.rx_1_to_64_packets
);
1746 print_port_stat_cond(&string_ext_stats
, "65_to_127_packets=",
1747 ps
->stats
.rx_65_to_127_packets
);
1748 print_port_stat_cond(&string_ext_stats
, "128_to_255_packets=",
1749 ps
->stats
.rx_128_to_255_packets
);
1750 print_port_stat_cond(&string_ext_stats
, "256_to_511_packets=",
1751 ps
->stats
.rx_256_to_511_packets
);
1752 print_port_stat_cond(&string_ext_stats
, "512_to_1023_packets=",
1753 ps
->stats
.rx_512_to_1023_packets
);
1754 print_port_stat_cond(&string_ext_stats
, "1024_to_1522_packets=",
1755 ps
->stats
.rx_1024_to_1522_packets
);
1756 print_port_stat_cond(&string_ext_stats
, "1523_to_max_packets=",
1757 ps
->stats
.rx_1523_to_max_packets
);
1758 print_port_stat_cond(&string_ext_stats
, "broadcast_packets=",
1759 ps
->stats
.rx_broadcast_packets
);
1760 print_port_stat_cond(&string_ext_stats
, "undersized_errors=",
1761 ps
->stats
.rx_undersized_errors
);
1762 print_port_stat_cond(&string_ext_stats
, "oversize_errors=",
1763 ps
->stats
.rx_oversize_errors
);
1764 print_port_stat_cond(&string_ext_stats
, "rx_fragmented_errors=",
1765 ps
->stats
.rx_fragmented_errors
);
1766 print_port_stat_cond(&string_ext_stats
, "rx_jabber_errors=",
1767 ps
->stats
.rx_jabber_errors
);
1769 if (string_ext_stats
.length
!= 0) {
1770 /* If at least one statistics counter is reported: */
1771 ds_put_cstr(string
, " rx rfc2819 ");
1772 ds_put_buffer(string
, string_ext_stats
.string
,
1773 string_ext_stats
.length
);
1774 ds_put_cstr(string
, "\n");
1775 ds_destroy(&string_ext_stats
);
1778 ds_init(&string_ext_stats
);
1780 print_port_stat_cond(&string_ext_stats
, "1_to_64_packets=",
1781 ps
->stats
.tx_1_to_64_packets
);
1782 print_port_stat_cond(&string_ext_stats
, "65_to_127_packets=",
1783 ps
->stats
.tx_65_to_127_packets
);
1784 print_port_stat_cond(&string_ext_stats
, "128_to_255_packets=",
1785 ps
->stats
.tx_128_to_255_packets
);
1786 print_port_stat_cond(&string_ext_stats
, "256_to_511_packets=",
1787 ps
->stats
.tx_256_to_511_packets
);
1788 print_port_stat_cond(&string_ext_stats
, "512_to_1023_packets=",
1789 ps
->stats
.tx_512_to_1023_packets
);
1790 print_port_stat_cond(&string_ext_stats
, "1024_to_1522_packets=",
1791 ps
->stats
.tx_1024_to_1522_packets
);
1792 print_port_stat_cond(&string_ext_stats
, "1523_to_max_packets=",
1793 ps
->stats
.tx_1523_to_max_packets
);
1794 print_port_stat_cond(&string_ext_stats
, "multicast_packets=",
1795 ps
->stats
.tx_multicast_packets
);
1796 print_port_stat_cond(&string_ext_stats
, "broadcast_packets=",
1797 ps
->stats
.tx_broadcast_packets
);
1799 if (string_ext_stats
.length
!= 0) {
1800 /* If at least one statistics counter is reported: */
1801 ds_put_cstr(string
, " tx rfc2819 ");
1802 ds_put_buffer(string
, string_ext_stats
.string
,
1803 string_ext_stats
.length
);
1804 ds_put_cstr(string
, "\n");
1805 ds_destroy(&string_ext_stats
);
1808 if (ps
->custom_stats
.size
) {
1809 ds_put_cstr(string
, " CUSTOM Statistics");
1810 for (int i
= 0; i
< ps
->custom_stats
.size
; i
++) {
1811 /* 3 counters in the row */
1812 if (ps
->custom_stats
.counters
[i
].name
[0]) {
1814 ds_put_cstr(string
, "\n");
1815 ds_put_cstr(string
, " ");
1817 ds_put_char(string
, ' ');
1819 ds_put_format(string
, "%s=%"PRIu64
",",
1820 ps
->custom_stats
.counters
[i
].name
,
1821 ps
->custom_stats
.counters
[i
].value
);
1824 ds_put_cstr(string
, "\n");
1829 /* Parse a port status request message into a 16 bit OpenFlow 1.0
1830 * port number and stores the latter in '*ofp10_port'.
1831 * Returns 0 if successful, otherwise an OFPERR_* number. */
1833 ofputil_decode_port_stats_request(const struct ofp_header
*request
,
1834 ofp_port_t
*ofp10_port
)
1836 switch ((enum ofp_version
)request
->version
) {
1841 case OFP11_VERSION
: {
1842 const struct ofp11_port_stats_request
*psr11
= ofpmsg_body(request
);
1843 return ofputil_port_from_ofp11(psr11
->port_no
, ofp10_port
);
1846 case OFP10_VERSION
: {
1847 const struct ofp10_port_stats_request
*psr10
= ofpmsg_body(request
);
1848 *ofp10_port
= u16_to_ofp(ntohs(psr10
->port_no
));