2 * Copyright (c) 2008, 2009, 2010 Nicira Networks.
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 "ofp-print.h"
22 #include <sys/types.h>
23 #include <netinet/in.h>
29 #include "byte-order.h"
31 #include "dynamic-string.h"
35 #include "openflow/openflow.h"
36 #include "openflow/nicira-ext.h"
41 static void ofp_print_port_name(struct ds *string, uint16_t port);
42 static void ofp_print_queue_name(struct ds *string, uint32_t port);
44 /* Returns a string that represents the contents of the Ethernet frame in the
45 * 'len' bytes starting at 'data' to 'stream' as output by tcpdump.
46 * 'total_len' specifies the full length of the Ethernet frame (of which 'len'
47 * bytes were captured).
49 * The caller must free the returned string.
51 * This starts and kills a tcpdump subprocess so it's quite expensive. */
53 ofp_packet_to_string(const void *data, size_t len, size_t total_len OVS_UNUSED)
55 struct ds ds = DS_EMPTY_INITIALIZER;
64 buf.data = (void *) data;
69 ovs_error(errno, "tmpfile");
70 return xstrdup("<error>");
72 pcap_write_header(pcap);
73 pcap_write(pcap, &buf);
76 ovs_error(errno, "error writing temporary file");
80 snprintf(command, sizeof command, "/usr/sbin/tcpdump -e -n -r /dev/fd/%d 2>/dev/null",
82 tcpdump = popen(command, "r");
85 ovs_error(errno, "exec(\"%s\")", command);
86 return xstrdup("<error>");
89 while ((c = getc(tcpdump)) != EOF) {
93 status = pclose(tcpdump);
94 if (WIFEXITED(status)) {
95 if (WEXITSTATUS(status))
96 ovs_error(0, "tcpdump exited with status %d", WEXITSTATUS(status));
97 } else if (WIFSIGNALED(status)) {
98 ovs_error(0, "tcpdump exited with signal %d", WTERMSIG(status));
103 /* Pretty-print the OFPT_PACKET_IN packet of 'len' bytes at 'oh' to 'stream'
104 * at the given 'verbosity' level. */
106 ofp_packet_in(struct ds *string, const void *oh, size_t len, int verbosity)
108 const struct ofp_packet_in *op = oh;
111 ds_put_format(string, " total_len=%"PRIu16" in_port=",
112 ntohs(op->total_len));
113 ofp_print_port_name(string, ntohs(op->in_port));
115 if (op->reason == OFPR_ACTION)
116 ds_put_cstr(string, " (via action)");
117 else if (op->reason != OFPR_NO_MATCH)
118 ds_put_format(string, " (***reason %"PRIu8"***)", op->reason);
120 data_len = len - offsetof(struct ofp_packet_in, data);
121 ds_put_format(string, " data_len=%zu", data_len);
122 if (htonl(op->buffer_id) == UINT32_MAX) {
123 ds_put_format(string, " (unbuffered)");
124 if (ntohs(op->total_len) != data_len)
125 ds_put_format(string, " (***total_len != data_len***)");
127 ds_put_format(string, " buffer=0x%08"PRIx32, ntohl(op->buffer_id));
128 if (ntohs(op->total_len) < data_len)
129 ds_put_format(string, " (***total_len < data_len***)");
131 ds_put_char(string, '\n');
135 struct ofpbuf packet;
136 struct ofp_match match;
137 packet.data = (void *) op->data;
138 packet.size = data_len;
139 flow_extract(&packet, 0, ntohs(op->in_port), &flow);
140 flow_to_match(&flow, 0, false, &match);
141 ofp_print_match(string, &match, verbosity);
142 ds_put_char(string, '\n');
145 char *packet = ofp_packet_to_string(op->data, data_len,
146 ntohs(op->total_len));
147 ds_put_cstr(string, packet);
152 static void ofp_print_port_name(struct ds *string, uint16_t port)
171 case OFPP_CONTROLLER:
181 ds_put_format(string, "%"PRIu16, port);
184 ds_put_cstr(string, name);
188 ofp_print_nx_action(struct ds *string, const struct nx_action_header *nah)
190 switch (ntohs(nah->subtype)) {
191 case NXAST_RESUBMIT: {
192 const struct nx_action_resubmit *nar = (struct nx_action_resubmit *)nah;
193 ds_put_format(string, "resubmit:");
194 ofp_print_port_name(string, ntohs(nar->in_port));
198 case NXAST_SET_TUNNEL: {
199 const struct nx_action_set_tunnel *nast =
200 (struct nx_action_set_tunnel *)nah;
201 ds_put_format(string, "set_tunnel:0x%08"PRIx32, ntohl(nast->tun_id));
205 case NXAST_DROP_SPOOFED_ARP:
206 ds_put_cstr(string, "drop_spoofed_arp");
209 case NXAST_SET_QUEUE: {
210 const struct nx_action_set_queue *nasq =
211 (struct nx_action_set_queue *)nah;
212 ds_put_format(string, "set_queue:%u", ntohl(nasq->queue_id));
216 case NXAST_POP_QUEUE:
217 ds_put_cstr(string, "pop_queue");
221 ds_put_format(string, "***unknown Nicira action:%d***",
222 ntohs(nah->subtype));
227 ofp_print_action(struct ds *string, const struct ofp_action_header *ah,
233 struct openflow_action {
238 const struct openflow_action of_actions[] = {
240 sizeof(struct ofp_action_output),
241 sizeof(struct ofp_action_output),
243 [OFPAT_SET_VLAN_VID] = {
244 sizeof(struct ofp_action_vlan_vid),
245 sizeof(struct ofp_action_vlan_vid),
247 [OFPAT_SET_VLAN_PCP] = {
248 sizeof(struct ofp_action_vlan_pcp),
249 sizeof(struct ofp_action_vlan_pcp),
251 [OFPAT_STRIP_VLAN] = {
252 sizeof(struct ofp_action_header),
253 sizeof(struct ofp_action_header),
255 [OFPAT_SET_DL_SRC] = {
256 sizeof(struct ofp_action_dl_addr),
257 sizeof(struct ofp_action_dl_addr),
259 [OFPAT_SET_DL_DST] = {
260 sizeof(struct ofp_action_dl_addr),
261 sizeof(struct ofp_action_dl_addr),
263 [OFPAT_SET_NW_SRC] = {
264 sizeof(struct ofp_action_nw_addr),
265 sizeof(struct ofp_action_nw_addr),
267 [OFPAT_SET_NW_DST] = {
268 sizeof(struct ofp_action_nw_addr),
269 sizeof(struct ofp_action_nw_addr),
271 [OFPAT_SET_NW_TOS] = {
272 sizeof(struct ofp_action_nw_tos),
273 sizeof(struct ofp_action_nw_tos),
275 [OFPAT_SET_TP_SRC] = {
276 sizeof(struct ofp_action_tp_port),
277 sizeof(struct ofp_action_tp_port),
279 [OFPAT_SET_TP_DST] = {
280 sizeof(struct ofp_action_tp_port),
281 sizeof(struct ofp_action_tp_port),
283 /* OFPAT_VENDOR is not here, since it would blow up the array size. */
286 if (actions_len < sizeof *ah) {
287 ds_put_format(string, "***action array too short for next action***\n");
291 type = ntohs(ah->type);
292 len = ntohs(ah->len);
293 if (actions_len < len) {
294 ds_put_format(string, "***truncated action %"PRIu16"***\n", type);
298 if ((len % OFP_ACTION_ALIGN) != 0) {
299 ds_put_format(string,
300 "***action %"PRIu16" length not a multiple of %d***\n",
301 type, OFP_ACTION_ALIGN);
305 if (type < ARRAY_SIZE(of_actions)) {
306 const struct openflow_action *act = &of_actions[type];
307 if ((len < act->min_size) || (len > act->max_size)) {
308 ds_put_format(string,
309 "***action %"PRIu16" wrong length: %zu***\n", type, len);
316 struct ofp_action_output *oa = (struct ofp_action_output *)ah;
317 uint16_t port = ntohs(oa->port);
318 if (port < OFPP_MAX) {
319 ds_put_format(string, "output:%"PRIu16, port);
321 ofp_print_port_name(string, port);
322 if (port == OFPP_CONTROLLER) {
324 ds_put_format(string, ":%"PRIu16, ntohs(oa->max_len));
326 ds_put_cstr(string, ":all");
333 case OFPAT_ENQUEUE: {
334 struct ofp_action_enqueue *ea = (struct ofp_action_enqueue *)ah;
335 unsigned int port = ntohs(ea->port);
336 unsigned int queue_id = ntohl(ea->queue_id);
337 ds_put_format(string, "enqueue:");
338 if (port != OFPP_IN_PORT) {
339 ds_put_format(string, "%u", port);
341 ds_put_cstr(string, "IN_PORT");
343 ds_put_format(string, "q%u", queue_id);
347 case OFPAT_SET_VLAN_VID: {
348 struct ofp_action_vlan_vid *va = (struct ofp_action_vlan_vid *)ah;
349 ds_put_format(string, "mod_vlan_vid:%"PRIu16, ntohs(va->vlan_vid));
353 case OFPAT_SET_VLAN_PCP: {
354 struct ofp_action_vlan_pcp *va = (struct ofp_action_vlan_pcp *)ah;
355 ds_put_format(string, "mod_vlan_pcp:%"PRIu8, va->vlan_pcp);
359 case OFPAT_STRIP_VLAN:
360 ds_put_cstr(string, "strip_vlan");
363 case OFPAT_SET_DL_SRC: {
364 struct ofp_action_dl_addr *da = (struct ofp_action_dl_addr *)ah;
365 ds_put_format(string, "mod_dl_src:"ETH_ADDR_FMT,
366 ETH_ADDR_ARGS(da->dl_addr));
370 case OFPAT_SET_DL_DST: {
371 struct ofp_action_dl_addr *da = (struct ofp_action_dl_addr *)ah;
372 ds_put_format(string, "mod_dl_dst:"ETH_ADDR_FMT,
373 ETH_ADDR_ARGS(da->dl_addr));
377 case OFPAT_SET_NW_SRC: {
378 struct ofp_action_nw_addr *na = (struct ofp_action_nw_addr *)ah;
379 ds_put_format(string, "mod_nw_src:"IP_FMT, IP_ARGS(&na->nw_addr));
383 case OFPAT_SET_NW_DST: {
384 struct ofp_action_nw_addr *na = (struct ofp_action_nw_addr *)ah;
385 ds_put_format(string, "mod_nw_dst:"IP_FMT, IP_ARGS(&na->nw_addr));
389 case OFPAT_SET_NW_TOS: {
390 struct ofp_action_nw_tos *nt = (struct ofp_action_nw_tos *)ah;
391 ds_put_format(string, "mod_nw_tos:%d", nt->nw_tos);
395 case OFPAT_SET_TP_SRC: {
396 struct ofp_action_tp_port *ta = (struct ofp_action_tp_port *)ah;
397 ds_put_format(string, "mod_tp_src:%d", ntohs(ta->tp_port));
401 case OFPAT_SET_TP_DST: {
402 struct ofp_action_tp_port *ta = (struct ofp_action_tp_port *)ah;
403 ds_put_format(string, "mod_tp_dst:%d", ntohs(ta->tp_port));
408 struct ofp_action_vendor_header *avh
409 = (struct ofp_action_vendor_header *)ah;
410 if (len < sizeof *avh) {
411 ds_put_format(string, "***ofpat_vendor truncated***\n");
414 if (avh->vendor == htonl(NX_VENDOR_ID)) {
415 ofp_print_nx_action(string, (struct nx_action_header *)avh);
417 ds_put_format(string, "vendor action:0x%x", ntohl(avh->vendor));
423 ds_put_format(string, "(decoder %"PRIu16" not implemented)", type);
431 ofp_print_actions(struct ds *string, const struct ofp_action_header *action,
434 uint8_t *p = (uint8_t *)action;
437 ds_put_cstr(string, "actions=");
439 ds_put_cstr(string, "drop");
441 while (actions_len > 0) {
443 ds_put_cstr(string, ",");
445 len = ofp_print_action(string, (struct ofp_action_header *)p,
455 /* Pretty-print the OFPT_PACKET_OUT packet of 'len' bytes at 'oh' to 'string'
456 * at the given 'verbosity' level. */
457 static void ofp_packet_out(struct ds *string, const void *oh, size_t len,
460 const struct ofp_packet_out *opo = oh;
461 size_t actions_len = ntohs(opo->actions_len);
463 ds_put_cstr(string, " in_port=");
464 ofp_print_port_name(string, ntohs(opo->in_port));
466 ds_put_format(string, " actions_len=%zu ", actions_len);
467 if (actions_len > (ntohs(opo->header.length) - sizeof *opo)) {
468 ds_put_format(string, "***packet too short for action length***\n");
471 ofp_print_actions(string, opo->actions, actions_len);
473 if (ntohl(opo->buffer_id) == UINT32_MAX) {
474 int data_len = len - sizeof *opo - actions_len;
475 ds_put_format(string, " data_len=%d", data_len);
476 if (verbosity > 0 && len > sizeof *opo) {
477 char *packet = ofp_packet_to_string(
478 (uint8_t *)opo->actions + actions_len, data_len, data_len);
479 ds_put_char(string, '\n');
480 ds_put_cstr(string, packet);
484 ds_put_format(string, " buffer=0x%08"PRIx32, ntohl(opo->buffer_id));
486 ds_put_char(string, '\n');
489 /* qsort comparison function. */
491 compare_ports(const void *a_, const void *b_)
493 const struct ofp_phy_port *a = a_;
494 const struct ofp_phy_port *b = b_;
495 uint16_t ap = ntohs(a->port_no);
496 uint16_t bp = ntohs(b->port_no);
498 return ap < bp ? -1 : ap > bp;
501 static void ofp_print_port_features(struct ds *string, uint32_t features)
504 ds_put_cstr(string, "Unsupported\n");
507 if (features & OFPPF_10MB_HD) {
508 ds_put_cstr(string, "10MB-HD ");
510 if (features & OFPPF_10MB_FD) {
511 ds_put_cstr(string, "10MB-FD ");
513 if (features & OFPPF_100MB_HD) {
514 ds_put_cstr(string, "100MB-HD ");
516 if (features & OFPPF_100MB_FD) {
517 ds_put_cstr(string, "100MB-FD ");
519 if (features & OFPPF_1GB_HD) {
520 ds_put_cstr(string, "1GB-HD ");
522 if (features & OFPPF_1GB_FD) {
523 ds_put_cstr(string, "1GB-FD ");
525 if (features & OFPPF_10GB_FD) {
526 ds_put_cstr(string, "10GB-FD ");
528 if (features & OFPPF_COPPER) {
529 ds_put_cstr(string, "COPPER ");
531 if (features & OFPPF_FIBER) {
532 ds_put_cstr(string, "FIBER ");
534 if (features & OFPPF_AUTONEG) {
535 ds_put_cstr(string, "AUTO_NEG ");
537 if (features & OFPPF_PAUSE) {
538 ds_put_cstr(string, "AUTO_PAUSE ");
540 if (features & OFPPF_PAUSE_ASYM) {
541 ds_put_cstr(string, "AUTO_PAUSE_ASYM ");
543 ds_put_char(string, '\n');
547 ofp_print_phy_port(struct ds *string, const struct ofp_phy_port *port)
549 uint8_t name[OFP_MAX_PORT_NAME_LEN];
552 memcpy(name, port->name, sizeof name);
553 for (j = 0; j < sizeof name - 1; j++) {
554 if (!isprint(name[j])) {
560 ds_put_char(string, ' ');
561 ofp_print_port_name(string, ntohs(port->port_no));
562 ds_put_format(string, "(%s): addr:"ETH_ADDR_FMT", config: %#x, state:%#x\n",
563 name, ETH_ADDR_ARGS(port->hw_addr), ntohl(port->config),
566 ds_put_format(string, " current: ");
567 ofp_print_port_features(string, ntohl(port->curr));
569 if (port->advertised) {
570 ds_put_format(string, " advertised: ");
571 ofp_print_port_features(string, ntohl(port->advertised));
573 if (port->supported) {
574 ds_put_format(string, " supported: ");
575 ofp_print_port_features(string, ntohl(port->supported));
578 ds_put_format(string, " peer: ");
579 ofp_print_port_features(string, ntohl(port->peer));
583 /* Pretty-print the struct ofp_switch_features of 'len' bytes at 'oh' to
584 * 'string' at the given 'verbosity' level. */
586 ofp_print_switch_features(struct ds *string, const void *oh, size_t len,
587 int verbosity OVS_UNUSED)
589 const struct ofp_switch_features *osf = oh;
590 struct ofp_phy_port *port_list;
594 ds_put_format(string, " ver:0x%x, dpid:%016"PRIx64"\n",
595 osf->header.version, ntohll(osf->datapath_id));
596 ds_put_format(string, "n_tables:%d, n_buffers:%d\n", osf->n_tables,
597 ntohl(osf->n_buffers));
598 ds_put_format(string, "features: capabilities:%#x, actions:%#x\n",
599 ntohl(osf->capabilities), ntohl(osf->actions));
601 if (ntohs(osf->header.length) >= sizeof *osf) {
602 len = MIN(len, ntohs(osf->header.length));
604 n_ports = (len - sizeof *osf) / sizeof *osf->ports;
606 port_list = xmemdup(osf->ports, len - sizeof *osf);
607 qsort(port_list, n_ports, sizeof *port_list, compare_ports);
608 for (i = 0; i < n_ports; i++) {
609 ofp_print_phy_port(string, &port_list[i]);
614 /* Pretty-print the struct ofp_switch_config of 'len' bytes at 'oh' to 'string'
615 * at the given 'verbosity' level. */
617 ofp_print_switch_config(struct ds *string, const void *oh,
618 size_t len OVS_UNUSED, int verbosity OVS_UNUSED)
620 const struct ofp_switch_config *osc = oh;
623 flags = ntohs(osc->flags);
625 ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***", flags);
628 ds_put_format(string, " miss_send_len=%"PRIu16"\n", ntohs(osc->miss_send_len));
631 static void print_wild(struct ds *string, const char *leader, int is_wild,
632 int verbosity, const char *format, ...)
633 __attribute__((format(printf, 5, 6)));
635 static void print_wild(struct ds *string, const char *leader, int is_wild,
636 int verbosity, const char *format, ...)
638 if (is_wild && verbosity < 2) {
641 ds_put_cstr(string, leader);
645 va_start(args, format);
646 ds_put_format_valist(string, format, args);
649 ds_put_char(string, '*');
651 ds_put_char(string, ',');
655 print_ip_netmask(struct ds *string, const char *leader, uint32_t ip,
656 uint32_t wild_bits, int verbosity)
658 if (wild_bits >= 32 && verbosity < 2) {
661 ds_put_cstr(string, leader);
662 if (wild_bits < 32) {
663 ds_put_format(string, IP_FMT, IP_ARGS(&ip));
665 ds_put_format(string, "/%d", 32 - wild_bits);
668 ds_put_char(string, '*');
670 ds_put_char(string, ',');
674 ofp_print_match(struct ds *f, const struct ofp_match *om, int verbosity)
676 char *s = ofp_match_to_string(om, verbosity);
682 ofp_match_to_string(const struct ofp_match *om, int verbosity)
684 struct ds f = DS_EMPTY_INITIALIZER;
685 uint32_t w = ntohl(om->wildcards);
686 bool skip_type = false;
687 bool skip_proto = false;
689 if (!(w & OFPFW_DL_TYPE)) {
691 if (om->dl_type == htons(ETH_TYPE_IP)) {
692 if (!(w & OFPFW_NW_PROTO)) {
694 if (om->nw_proto == IP_TYPE_ICMP) {
695 ds_put_cstr(&f, "icmp,");
696 } else if (om->nw_proto == IP_TYPE_TCP) {
697 ds_put_cstr(&f, "tcp,");
698 } else if (om->nw_proto == IP_TYPE_UDP) {
699 ds_put_cstr(&f, "udp,");
701 ds_put_cstr(&f, "ip,");
705 ds_put_cstr(&f, "ip,");
707 } else if (om->dl_type == htons(ETH_TYPE_ARP)) {
708 ds_put_cstr(&f, "arp,");
713 if (w & NXFW_TUN_ID) {
714 ds_put_cstr(&f, "tun_id_wild,");
716 print_wild(&f, "in_port=", w & OFPFW_IN_PORT, verbosity,
717 "%d", ntohs(om->in_port));
718 print_wild(&f, "dl_vlan=", w & OFPFW_DL_VLAN, verbosity,
719 "%d", ntohs(om->dl_vlan));
720 print_wild(&f, "dl_vlan_pcp=", w & OFPFW_DL_VLAN_PCP, verbosity,
721 "%d", om->dl_vlan_pcp);
722 print_wild(&f, "dl_src=", w & OFPFW_DL_SRC, verbosity,
723 ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_src));
724 print_wild(&f, "dl_dst=", w & OFPFW_DL_DST, verbosity,
725 ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_dst));
727 print_wild(&f, "dl_type=", w & OFPFW_DL_TYPE, verbosity,
728 "0x%04x", ntohs(om->dl_type));
730 print_ip_netmask(&f, "nw_src=", om->nw_src,
731 (w & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT, verbosity);
732 print_ip_netmask(&f, "nw_dst=", om->nw_dst,
733 (w & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT, verbosity);
735 if (om->dl_type == htons(ETH_TYPE_ARP)) {
736 print_wild(&f, "opcode=", w & OFPFW_NW_PROTO, verbosity,
739 print_wild(&f, "nw_proto=", w & OFPFW_NW_PROTO, verbosity,
743 print_wild(&f, "nw_tos=", w & OFPFW_NW_TOS, verbosity,
745 if (om->nw_proto == IP_TYPE_ICMP) {
746 print_wild(&f, "icmp_type=", w & OFPFW_ICMP_TYPE, verbosity,
747 "%d", ntohs(om->icmp_type));
748 print_wild(&f, "icmp_code=", w & OFPFW_ICMP_CODE, verbosity,
749 "%d", ntohs(om->icmp_code));
751 print_wild(&f, "tp_src=", w & OFPFW_TP_SRC, verbosity,
752 "%d", ntohs(om->tp_src));
753 print_wild(&f, "tp_dst=", w & OFPFW_TP_DST, verbosity,
754 "%d", ntohs(om->tp_dst));
759 /* Pretty-print the OFPT_FLOW_MOD packet of 'len' bytes at 'oh' to 'string'
760 * at the given 'verbosity' level. */
762 ofp_print_flow_mod(struct ds *string, const void *oh, size_t len,
765 const struct ofp_flow_mod *ofm = oh;
767 ds_put_char(string, ' ');
768 ofp_print_match(string, &ofm->match, verbosity);
769 if (ds_last(string) != ' ') {
770 ds_put_char(string, ' ');
773 switch (ntohs(ofm->command)) {
775 ds_put_cstr(string, "ADD:");
778 ds_put_cstr(string, "MOD:");
780 case OFPFC_MODIFY_STRICT:
781 ds_put_cstr(string, "MOD_STRICT:");
784 ds_put_cstr(string, "DEL:");
786 case OFPFC_DELETE_STRICT:
787 ds_put_cstr(string, "DEL_STRICT:");
790 ds_put_format(string, "cmd:%d", ntohs(ofm->command));
792 if (ofm->cookie != htonll(0)) {
793 ds_put_format(string, " cookie:0x%"PRIx64, ntohll(ofm->cookie));
795 if (ofm->idle_timeout != htons(OFP_FLOW_PERMANENT)) {
796 ds_put_format(string, " idle:%d", ntohs(ofm->idle_timeout));
798 if (ofm->hard_timeout != htons(OFP_FLOW_PERMANENT)) {
799 ds_put_format(string, " hard:%d", ntohs(ofm->hard_timeout));
801 if (ofm->priority != htons(32768)) {
802 ds_put_format(string, " pri:%"PRIu16, ntohs(ofm->priority));
804 if (ofm->buffer_id != htonl(UINT32_MAX)) {
805 ds_put_format(string, " buf:%#"PRIx32, ntohl(ofm->buffer_id));
807 if (ofm->flags != htons(0)) {
808 ds_put_format(string, " flags:%"PRIx16, ntohs(ofm->flags));
810 ds_put_cstr(string, " ");
811 ofp_print_actions(string, ofm->actions,
812 len - offsetof(struct ofp_flow_mod, actions));
813 ds_put_char(string, '\n');
816 /* Pretty-print the OFPT_FLOW_REMOVED packet of 'len' bytes at 'oh' to 'string'
817 * at the given 'verbosity' level. */
819 ofp_print_flow_removed(struct ds *string, const void *oh,
820 size_t len OVS_UNUSED, int verbosity)
822 const struct ofp_flow_removed *ofr = oh;
824 ofp_print_match(string, &ofr->match, verbosity);
825 ds_put_cstr(string, " reason=");
826 switch (ofr->reason) {
827 case OFPRR_IDLE_TIMEOUT:
828 ds_put_cstr(string, "idle");
830 case OFPRR_HARD_TIMEOUT:
831 ds_put_cstr(string, "hard");
834 ds_put_cstr(string, "delete");
837 ds_put_format(string, "**%"PRIu8"**", ofr->reason);
841 if (ofr->cookie != htonll(0)) {
842 ds_put_format(string, " cookie:0x%"PRIx64, ntohll(ofr->cookie));
844 if (ofr->priority != htons(32768)) {
845 ds_put_format(string, " pri:%"PRIu16, ntohs(ofr->priority));
847 ds_put_format(string, " secs%"PRIu32" nsecs%"PRIu32
848 " idle%"PRIu16" pkts%"PRIu64" bytes%"PRIu64"\n",
849 ntohl(ofr->duration_sec), ntohl(ofr->duration_nsec),
850 ntohs(ofr->idle_timeout), ntohll(ofr->packet_count),
851 ntohll(ofr->byte_count));
855 ofp_print_port_mod(struct ds *string, const void *oh, size_t len OVS_UNUSED,
856 int verbosity OVS_UNUSED)
858 const struct ofp_port_mod *opm = oh;
860 ds_put_format(string, "port: %d: addr:"ETH_ADDR_FMT", config: %#x, mask:%#x\n",
861 ntohs(opm->port_no), ETH_ADDR_ARGS(opm->hw_addr),
862 ntohl(opm->config), ntohl(opm->mask));
863 ds_put_format(string, " advertise: ");
864 if (opm->advertise) {
865 ofp_print_port_features(string, ntohl(opm->advertise));
867 ds_put_format(string, "UNCHANGED\n");
877 static const struct error_type error_types[] = {
878 #define ERROR_TYPE(TYPE) {TYPE, -1, #TYPE}
879 #define ERROR_CODE(TYPE, CODE) {TYPE, CODE, #CODE}
880 ERROR_TYPE(OFPET_HELLO_FAILED),
881 ERROR_CODE(OFPET_HELLO_FAILED, OFPHFC_INCOMPATIBLE),
882 ERROR_CODE(OFPET_HELLO_FAILED, OFPHFC_EPERM),
884 ERROR_TYPE(OFPET_BAD_REQUEST),
885 ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION),
886 ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE),
887 ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_STAT),
888 ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR),
889 ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE),
890 ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_EPERM),
891 ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN),
892 ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BUFFER_EMPTY),
893 ERROR_CODE(OFPET_BAD_REQUEST, OFPBRC_BUFFER_UNKNOWN),
895 ERROR_TYPE(OFPET_BAD_ACTION),
896 ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_TYPE),
897 ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_LEN),
898 ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR),
899 ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR_TYPE),
900 ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT),
901 ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT),
902 ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_EPERM),
903 ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_TOO_MANY),
905 ERROR_TYPE(OFPET_FLOW_MOD_FAILED),
906 ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL),
907 ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP),
908 ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_EPERM),
909 ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_EMERG_TIMEOUT),
910 ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_COMMAND),
912 ERROR_TYPE(OFPET_PORT_MOD_FAILED),
913 ERROR_CODE(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_PORT),
914 ERROR_CODE(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_HW_ADDR)
916 #define N_ERROR_TYPES ARRAY_SIZE(error_types)
919 lookup_error_type(int type)
921 const struct error_type *t;
923 for (t = error_types; t < &error_types[N_ERROR_TYPES]; t++) {
924 if (t->type == type && t->code == -1) {
932 lookup_error_code(int type, int code)
934 const struct error_type *t;
936 for (t = error_types; t < &error_types[N_ERROR_TYPES]; t++) {
937 if (t->type == type && t->code == code) {
944 /* Pretty-print the OFPT_ERROR packet of 'len' bytes at 'oh' to 'string'
945 * at the given 'verbosity' level. */
947 ofp_print_error_msg(struct ds *string, const void *oh, size_t len,
948 int verbosity OVS_UNUSED)
950 const struct ofp_error_msg *oem = oh;
951 int type = ntohs(oem->type);
952 int code = ntohs(oem->code);
955 ds_put_format(string, " type%d(%s) code%d(%s) payload:\n",
956 type, lookup_error_type(type),
957 code, lookup_error_code(type, code));
960 case OFPET_HELLO_FAILED:
961 ds_put_printable(string, (char *) oem->data, len - sizeof *oem);
964 case OFPET_BAD_REQUEST:
965 s = ofp_to_string(oem->data, len - sizeof *oem, 1);
966 ds_put_cstr(string, s);
971 ds_put_hex_dump(string, oem->data, len - sizeof *oem, 0, true);
976 /* Pretty-print the OFPT_PORT_STATUS packet of 'len' bytes at 'oh' to 'string'
977 * at the given 'verbosity' level. */
979 ofp_print_port_status(struct ds *string, const void *oh, size_t len OVS_UNUSED,
980 int verbosity OVS_UNUSED)
982 const struct ofp_port_status *ops = oh;
984 if (ops->reason == OFPPR_ADD) {
985 ds_put_format(string, " ADD:");
986 } else if (ops->reason == OFPPR_DELETE) {
987 ds_put_format(string, " DEL:");
988 } else if (ops->reason == OFPPR_MODIFY) {
989 ds_put_format(string, " MOD:");
992 ofp_print_phy_port(string, &ops->desc);
996 ofp_desc_stats_reply(struct ds *string, const void *body,
997 size_t len OVS_UNUSED, int verbosity OVS_UNUSED)
999 const struct ofp_desc_stats *ods = body;
1001 ds_put_format(string, "Manufacturer: %.*s\n",
1002 (int) sizeof ods->mfr_desc, ods->mfr_desc);
1003 ds_put_format(string, "Hardware: %.*s\n",
1004 (int) sizeof ods->hw_desc, ods->hw_desc);
1005 ds_put_format(string, "Software: %.*s\n",
1006 (int) sizeof ods->sw_desc, ods->sw_desc);
1007 ds_put_format(string, "Serial Num: %.*s\n",
1008 (int) sizeof ods->serial_num, ods->serial_num);
1009 ds_put_format(string, "DP Description: %.*s\n",
1010 (int) sizeof ods->dp_desc, ods->dp_desc);
1014 ofp_flow_stats_request(struct ds *string, const void *oh,
1015 size_t len OVS_UNUSED, int verbosity)
1017 const struct ofp_flow_stats_request *fsr = oh;
1019 if (fsr->table_id == 0xff) {
1020 ds_put_format(string, " table_id=any, ");
1022 ds_put_format(string, " table_id=%"PRIu8", ", fsr->table_id);
1025 ofp_print_match(string, &fsr->match, verbosity);
1029 ofp_flow_stats_reply(struct ds *string, const void *body_, size_t len,
1032 const char *body = body_;
1033 const char *pos = body;
1035 const struct ofp_flow_stats *fs;
1036 ptrdiff_t bytes_left = body + len - pos;
1039 if (bytes_left < sizeof *fs) {
1040 if (bytes_left != 0) {
1041 ds_put_format(string, " ***%td leftover bytes at end***",
1047 fs = (const void *) pos;
1048 length = ntohs(fs->length);
1049 if (length < sizeof *fs) {
1050 ds_put_format(string, " ***length=%zu shorter than minimum %zu***",
1051 length, sizeof *fs);
1053 } else if (length > bytes_left) {
1054 ds_put_format(string,
1055 " ***length=%zu but only %td bytes left***",
1056 length, bytes_left);
1058 } else if ((length - sizeof *fs) % sizeof fs->actions[0]) {
1059 ds_put_format(string,
1060 " ***length=%zu has %zu bytes leftover in "
1063 (length - sizeof *fs) % sizeof fs->actions[0]);
1067 ds_put_format(string, " cookie=0x%"PRIx64", ", ntohll(fs->cookie));
1068 ds_put_format(string, "duration_sec=%"PRIu32"s, ",
1069 ntohl(fs->duration_sec));
1070 ds_put_format(string, "duration_nsec=%"PRIu32"ns, ",
1071 ntohl(fs->duration_nsec));
1072 ds_put_format(string, "table_id=%"PRIu8", ", fs->table_id);
1073 ds_put_format(string, "priority=%"PRIu16", ",
1074 fs->match.wildcards ? ntohs(fs->priority) : (uint16_t)-1);
1075 ds_put_format(string, "n_packets=%"PRIu64", ",
1076 ntohll(fs->packet_count));
1077 ds_put_format(string, "n_bytes=%"PRIu64", ", ntohll(fs->byte_count));
1078 if (fs->idle_timeout != htons(OFP_FLOW_PERMANENT)) {
1079 ds_put_format(string, "idle_timeout=%"PRIu16",",
1080 ntohs(fs->idle_timeout));
1082 if (fs->hard_timeout != htons(OFP_FLOW_PERMANENT)) {
1083 ds_put_format(string, "hard_timeout=%"PRIu16",",
1084 ntohs(fs->hard_timeout));
1086 ofp_print_match(string, &fs->match, verbosity);
1087 ofp_print_actions(string, fs->actions, length - sizeof *fs);
1088 ds_put_char(string, '\n');
1095 ofp_aggregate_stats_request(struct ds *string, const void *oh,
1096 size_t len OVS_UNUSED, int verbosity)
1098 const struct ofp_aggregate_stats_request *asr = oh;
1100 if (asr->table_id == 0xff) {
1101 ds_put_format(string, " table_id=any, ");
1103 ds_put_format(string, " table_id=%"PRIu8", ", asr->table_id);
1106 ofp_print_match(string, &asr->match, verbosity);
1110 ofp_aggregate_stats_reply(struct ds *string, const void *body_,
1111 size_t len OVS_UNUSED, int verbosity OVS_UNUSED)
1113 const struct ofp_aggregate_stats_reply *asr = body_;
1115 ds_put_format(string, " packet_count=%"PRIu64, ntohll(asr->packet_count));
1116 ds_put_format(string, " byte_count=%"PRIu64, ntohll(asr->byte_count));
1117 ds_put_format(string, " flow_count=%"PRIu32, ntohl(asr->flow_count));
1120 static void print_port_stat(struct ds *string, const char *leader,
1121 uint64_t stat, int more)
1123 ds_put_cstr(string, leader);
1125 ds_put_format(string, "%"PRIu64, stat);
1127 ds_put_char(string, '?');
1130 ds_put_cstr(string, ", ");
1132 ds_put_cstr(string, "\n");
1137 ofp_port_stats_request(struct ds *string, const void *body_,
1138 size_t len OVS_UNUSED, int verbosity OVS_UNUSED)
1140 const struct ofp_port_stats_request *psr = body_;
1141 ds_put_format(string, "port_no=%"PRIu16, ntohs(psr->port_no));
1145 ofp_port_stats_reply(struct ds *string, const void *body, size_t len,
1148 const struct ofp_port_stats *ps = body;
1149 size_t n = len / sizeof *ps;
1150 ds_put_format(string, " %zu ports\n", n);
1151 if (verbosity < 1) {
1156 ds_put_format(string, " port %2"PRIu16": ", ntohs(ps->port_no));
1158 ds_put_cstr(string, "rx ");
1159 print_port_stat(string, "pkts=", ntohll(ps->rx_packets), 1);
1160 print_port_stat(string, "bytes=", ntohll(ps->rx_bytes), 1);
1161 print_port_stat(string, "drop=", ntohll(ps->rx_dropped), 1);
1162 print_port_stat(string, "errs=", ntohll(ps->rx_errors), 1);
1163 print_port_stat(string, "frame=", ntohll(ps->rx_frame_err), 1);
1164 print_port_stat(string, "over=", ntohll(ps->rx_over_err), 1);
1165 print_port_stat(string, "crc=", ntohll(ps->rx_crc_err), 0);
1167 ds_put_cstr(string, " tx ");
1168 print_port_stat(string, "pkts=", ntohll(ps->tx_packets), 1);
1169 print_port_stat(string, "bytes=", ntohll(ps->tx_bytes), 1);
1170 print_port_stat(string, "drop=", ntohll(ps->tx_dropped), 1);
1171 print_port_stat(string, "errs=", ntohll(ps->tx_errors), 1);
1172 print_port_stat(string, "coll=", ntohll(ps->collisions), 0);
1177 ofp_table_stats_reply(struct ds *string, const void *body, size_t len,
1180 const struct ofp_table_stats *ts = body;
1181 size_t n = len / sizeof *ts;
1182 ds_put_format(string, " %zu tables\n", n);
1183 if (verbosity < 1) {
1188 char name[OFP_MAX_TABLE_NAME_LEN + 1];
1189 strncpy(name, ts->name, sizeof name);
1190 name[OFP_MAX_TABLE_NAME_LEN] = '\0';
1192 ds_put_format(string, " %d: %-8s: ", ts->table_id, name);
1193 ds_put_format(string, "wild=0x%05"PRIx32", ", ntohl(ts->wildcards));
1194 ds_put_format(string, "max=%6"PRIu32", ", ntohl(ts->max_entries));
1195 ds_put_format(string, "active=%"PRIu32"\n", ntohl(ts->active_count));
1196 ds_put_cstr(string, " ");
1197 ds_put_format(string, "lookup=%"PRIu64", ",
1198 ntohll(ts->lookup_count));
1199 ds_put_format(string, "matched=%"PRIu64"\n",
1200 ntohll(ts->matched_count));
1205 ofp_print_queue_name(struct ds *string, uint32_t queue_id)
1207 if (queue_id == OFPQ_ALL) {
1208 ds_put_cstr(string, "ALL");
1210 ds_put_format(string, "%"PRIu32, queue_id);
1215 ofp_queue_stats_request(struct ds *string, const void *body_,
1216 size_t len OVS_UNUSED, int verbosity OVS_UNUSED)
1218 const struct ofp_queue_stats_request *qsr = body_;
1220 ds_put_cstr(string, "port=");
1221 ofp_print_port_name(string, ntohs(qsr->port_no));
1223 ds_put_cstr(string, " queue=");
1224 ofp_print_queue_name(string, ntohl(qsr->queue_id));
1228 ofp_queue_stats_reply(struct ds *string, const void *body, size_t len,
1231 const struct ofp_queue_stats *qs = body;
1232 size_t n = len / sizeof *qs;
1233 ds_put_format(string, " %zu queues\n", n);
1234 if (verbosity < 1) {
1239 ds_put_cstr(string, " port ");
1240 ofp_print_port_name(string, ntohs(qs->port_no));
1241 ds_put_cstr(string, " queue ");
1242 ofp_print_queue_name(string, ntohl(qs->queue_id));
1243 ds_put_cstr(string, ": ");
1245 print_port_stat(string, "bytes=", ntohll(qs->tx_bytes), 1);
1246 print_port_stat(string, "pkts=", ntohll(qs->tx_packets), 1);
1247 print_port_stat(string, "errors=", ntohll(qs->tx_errors), 0);
1252 vendor_stat(struct ds *string, const void *body, size_t len,
1253 int verbosity OVS_UNUSED)
1255 ds_put_format(string, " vendor=%08"PRIx32, ntohl(*(uint32_t *) body));
1256 ds_put_format(string, " %zu bytes additional data",
1257 len - sizeof(uint32_t));
1260 enum stats_direction {
1266 print_stats(struct ds *string, int type, const void *body, size_t body_len,
1267 int verbosity, enum stats_direction direction)
1270 size_t min_body, max_body;
1271 void (*printer)(struct ds *, const void *, size_t len, int verbosity);
1277 struct stats_msg request;
1278 struct stats_msg reply;
1281 static const struct stats_type stats_types[] = {
1286 { 0, SIZE_MAX, ofp_desc_stats_reply },
1291 { sizeof(struct ofp_flow_stats_request),
1292 sizeof(struct ofp_flow_stats_request),
1293 ofp_flow_stats_request },
1294 { 0, SIZE_MAX, ofp_flow_stats_reply },
1299 { sizeof(struct ofp_aggregate_stats_request),
1300 sizeof(struct ofp_aggregate_stats_request),
1301 ofp_aggregate_stats_request },
1302 { sizeof(struct ofp_aggregate_stats_reply),
1303 sizeof(struct ofp_aggregate_stats_reply),
1304 ofp_aggregate_stats_reply },
1310 { 0, SIZE_MAX, ofp_table_stats_reply },
1315 { sizeof(struct ofp_port_stats_request),
1316 sizeof(struct ofp_port_stats_request),
1317 ofp_port_stats_request },
1318 { 0, SIZE_MAX, ofp_port_stats_reply },
1323 { sizeof(struct ofp_queue_stats_request),
1324 sizeof(struct ofp_queue_stats_request),
1325 ofp_queue_stats_request },
1326 { 0, SIZE_MAX, ofp_queue_stats_reply },
1331 { sizeof(uint32_t), SIZE_MAX, vendor_stat },
1332 { sizeof(uint32_t), SIZE_MAX, vendor_stat },
1342 const struct stats_type *s;
1343 const struct stats_msg *m;
1345 if (type >= ARRAY_SIZE(stats_types) || !stats_types[type].name) {
1346 ds_put_format(string, " ***unknown type %d***", type);
1349 for (s = stats_types; s->type >= 0; s++) {
1350 if (s->type == type) {
1354 ds_put_format(string, " type=%d(%s)\n", type, s->name);
1356 m = direction == REQUEST ? &s->request : &s->reply;
1357 if (body_len < m->min_body || body_len > m->max_body) {
1358 ds_put_format(string, " ***body_len=%zu not in %zu...%zu***",
1359 body_len, m->min_body, m->max_body);
1363 m->printer(string, body, body_len, verbosity);
1368 ofp_stats_request(struct ds *string, const void *oh, size_t len, int verbosity)
1370 const struct ofp_stats_request *srq = oh;
1373 ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***",
1377 print_stats(string, ntohs(srq->type), srq->body,
1378 len - offsetof(struct ofp_stats_request, body),
1379 verbosity, REQUEST);
1383 ofp_stats_reply(struct ds *string, const void *oh, size_t len, int verbosity)
1385 const struct ofp_stats_reply *srp = oh;
1387 ds_put_cstr(string, " flags=");
1389 ds_put_cstr(string, "none");
1391 uint16_t flags = ntohs(srp->flags);
1392 if (flags & OFPSF_REPLY_MORE) {
1393 ds_put_cstr(string, "[more]");
1394 flags &= ~OFPSF_REPLY_MORE;
1397 ds_put_format(string, "[***unknown flags 0x%04"PRIx16"***]", flags);
1401 print_stats(string, ntohs(srp->type), srp->body,
1402 len - offsetof(struct ofp_stats_reply, body),
1407 ofp_echo(struct ds *string, const void *oh, size_t len, int verbosity)
1409 const struct ofp_header *hdr = oh;
1411 ds_put_format(string, " %zu bytes of payload\n", len - sizeof *hdr);
1412 if (verbosity > 1) {
1413 ds_put_hex_dump(string, hdr, len - sizeof *hdr, 0, true);
1417 struct openflow_packet {
1421 void (*printer)(struct ds *, const void *, size_t len, int verbosity);
1424 static const struct openflow_packet packets[] = {
1428 sizeof (struct ofp_header),
1432 OFPT_FEATURES_REQUEST,
1434 sizeof (struct ofp_header),
1438 OFPT_FEATURES_REPLY,
1440 sizeof (struct ofp_switch_features),
1441 ofp_print_switch_features,
1444 OFPT_GET_CONFIG_REQUEST,
1445 "get_config_request",
1446 sizeof (struct ofp_header),
1450 OFPT_GET_CONFIG_REPLY,
1452 sizeof (struct ofp_switch_config),
1453 ofp_print_switch_config,
1458 sizeof (struct ofp_switch_config),
1459 ofp_print_switch_config,
1464 offsetof(struct ofp_packet_in, data),
1470 sizeof (struct ofp_packet_out),
1476 sizeof (struct ofp_flow_mod),
1482 sizeof (struct ofp_flow_removed),
1483 ofp_print_flow_removed,
1488 sizeof (struct ofp_port_mod),
1494 sizeof (struct ofp_port_status),
1495 ofp_print_port_status
1500 sizeof (struct ofp_error_msg),
1501 ofp_print_error_msg,
1506 sizeof (struct ofp_stats_request),
1512 sizeof (struct ofp_stats_reply),
1518 sizeof (struct ofp_header),
1524 sizeof (struct ofp_header),
1530 sizeof (struct ofp_vendor_header),
1534 OFPT_BARRIER_REQUEST,
1536 sizeof (struct ofp_header),
1542 sizeof (struct ofp_header),
1547 /* Composes and returns a string representing the OpenFlow packet of 'len'
1548 * bytes at 'oh' at the given 'verbosity' level. 0 is a minimal amount of
1549 * verbosity and higher numbers increase verbosity. The caller is responsible
1550 * for freeing the string. */
1552 ofp_to_string(const void *oh_, size_t len, int verbosity)
1554 struct ds string = DS_EMPTY_INITIALIZER;
1555 const struct ofp_header *oh = oh_;
1556 const struct openflow_packet *pkt;
1558 if (len < sizeof(struct ofp_header)) {
1559 ds_put_cstr(&string, "OpenFlow packet too short:\n");
1560 ds_put_hex_dump(&string, oh, len, 0, true);
1561 return ds_cstr(&string);
1562 } else if (oh->version != OFP_VERSION) {
1563 ds_put_format(&string, "Bad OpenFlow version %"PRIu8":\n", oh->version);
1564 ds_put_hex_dump(&string, oh, len, 0, true);
1565 return ds_cstr(&string);
1568 for (pkt = packets; ; pkt++) {
1569 if (pkt >= &packets[ARRAY_SIZE(packets)]) {
1570 ds_put_format(&string, "Unknown OpenFlow packet type %"PRIu8":\n",
1572 ds_put_hex_dump(&string, oh, len, 0, true);
1573 return ds_cstr(&string);
1574 } else if (oh->type == pkt->type) {
1579 ds_put_format(&string, "%s (xid=0x%"PRIx32"):", pkt->name, oh->xid);
1581 if (ntohs(oh->length) > len)
1582 ds_put_format(&string, " (***truncated to %zu bytes from %"PRIu16"***)",
1583 len, ntohs(oh->length));
1584 else if (ntohs(oh->length) < len) {
1585 ds_put_format(&string, " (***only uses %"PRIu16" bytes out of %zu***)\n",
1586 ntohs(oh->length), len);
1587 len = ntohs(oh->length);
1590 if (len < pkt->min_size) {
1591 ds_put_format(&string, " (***length=%zu < min_size=%zu***)\n",
1592 len, pkt->min_size);
1593 } else if (!pkt->printer) {
1594 if (len > sizeof *oh) {
1595 ds_put_format(&string, " length=%"PRIu16" (decoder not implemented)\n",
1599 pkt->printer(&string, oh, len, verbosity);
1601 if (verbosity >= 3) {
1602 ds_put_hex_dump(&string, oh, len, 0, true);
1604 if (string.string[string.length - 1] != '\n') {
1605 ds_put_char(&string, '\n');
1607 return ds_cstr(&string);
1610 /* Returns the name for the specified OpenFlow message type as a string,
1611 * e.g. "OFPT_FEATURES_REPLY". If no name is known, the string returned is a
1612 * hex number, e.g. "0x55".
1614 * The caller must free the returned string when it is no longer needed. */
1616 ofp_message_type_to_string(uint8_t type)
1618 struct ds s = DS_EMPTY_INITIALIZER;
1619 const struct openflow_packet *pkt;
1620 for (pkt = packets; ; pkt++) {
1621 if (pkt >= &packets[ARRAY_SIZE(packets)]) {
1622 ds_put_format(&s, "0x%02"PRIx8, type);
1624 } else if (type == pkt->type) {
1627 ds_put_cstr(&s, "OFPT_");
1628 for (p = pkt->name; *p; p++) {
1629 ds_put_char(&s, toupper((unsigned char) *p));
1638 print_and_free(FILE *stream, char *string)
1640 fputs(string, stream);
1644 /* Pretty-print the OpenFlow packet of 'len' bytes at 'oh' to 'stream' at the
1645 * given 'verbosity' level. 0 is a minimal amount of verbosity and higher
1646 * numbers increase verbosity. */
1648 ofp_print(FILE *stream, const void *oh, size_t len, int verbosity)
1650 print_and_free(stream, ofp_to_string(oh, len, verbosity));
1653 /* Dumps the contents of the Ethernet frame in the 'len' bytes starting at
1654 * 'data' to 'stream' using tcpdump. 'total_len' specifies the full length of
1655 * the Ethernet frame (of which 'len' bytes were captured).
1657 * This starts and kills a tcpdump subprocess so it's quite expensive. */
1659 ofp_print_packet(FILE *stream, const void *data, size_t len, size_t total_len)
1661 print_and_free(stream, ofp_packet_to_string(data, len, total_len));